func_timeout
Run any existing Python function with a hard timeout, plus stoppable-thread support
Repository Health
Technical Analysis
func_timeout lets you call any existing function with a maximum execution time without modifying that function’s code. func_timeout(timeout, func, args, kwargs) runs the target in a background StoppableThread, returns its result or re-raises its exception as normal, and raises FunctionTimedOut if the deadline passes — at which point it can even attempt to stop the thread mid-execution and unwind a partial stack trace.
What You Get
func_timeout(timeout, func, args, kwargs)— call any function with a wall-clock timeout, propagating its return value or exception@func_set_timeout(timeout)decorator to bake a timeout into a function definitionStoppableThread— athreading.Threadsubclass that supports raising an exception inside the running thread to stop itFunctionTimedOutexception carrying the original call’s args/kwargs for diagnostics- Cross Python 2/3 support with dedicated exception-raising shims for each
Common Use Cases
- Bounding execution time for third-party functions you can’t modify (parsing, network calls, legacy code)
- Preventing a single slow operation from hanging a batch job or worker process indefinitely
- Adding a timeout guard around blocking calls in scripts that don’t natively support cancellation
- Building test harnesses that need to fail fast when a function under test hangs
Under The Hood
Architecture: dafunc.py implements func_timeout by starting the target function on a StoppableThread (StoppableThread.py) and joining it with the given timeout; if the thread hasn’t finished, it calls the thread’s stop() method, which uses the CPython C API (ctypes.pythonapi.PyThreadState_SetAsyncExc) to asynchronously raise an exception inside the target thread’s frame, then raises FunctionTimedOut in the caller. Tech Stack: pure Python standard library only (threading, ctypes) with no third-party runtime dependencies, and separate py2_raise.py/py3_raise.py modules to handle the syntax differences in exception re-raising across Python versions. Code Quality: a tests/runTests.py suite exercises timeout firing, successful completion, and exception propagation; the codebase is small (a few hundred lines total) and largely stable, though it has seen little maintenance activity in recent years. API Design: the API surface is deliberately tiny — one function, one decorator, one exception class — trading fine-grained cancellation semantics (async-exception-based thread stopping is inherently best-effort in CPython) for near-zero integration cost into existing synchronous code.