{"id":7759,"library":"stopit","title":"stopit: Timeout Control for Python","description":"stopit is a Python library that provides flexible mechanisms for controlling the execution time of code blocks and functions. It offers both context managers and decorators to enforce timeouts and can raise exceptions in other threads. The current version is 1.1.2, with its last major update in 2018, indicating a maintenance-focused release cadence.","status":"maintenance","version":"1.1.2","language":"en","source_language":"en","source_url":"https://github.com/glenfant/stopit","tags":["timeout","context-manager","decorator","threading","exception","control-flow"],"install":[{"cmd":"pip install stopit","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"note":"The class was renamed in v1.1.0; 'Timeout' is deprecated.","wrong":"from stopit import Timeout","symbol":"ThreadingTimeout","correct":"from stopit import ThreadingTimeout"},{"note":"The decorator was renamed in v1.1.0; 'timeoutable' is deprecated.","wrong":"from stopit import timeoutable","symbol":"threading_timeoutable","correct":"from stopit import threading_timeoutable"},{"symbol":"TimeoutException","correct":"from stopit import TimeoutException"},{"symbol":"async_raise","correct":"from stopit import async_raise"}],"quickstart":{"code":"import stopit\nimport time\n\nprint(\"Starting long running task with 5-second timeout...\")\nwith stopit.ThreadingTimeout(5) as context_manager:\n    # Simulate a long-running operation\n    for i in range(10**8):\n        _ = i * 2 # Some computation\n        if not context_manager.state == context_manager.EXECUTING: # Optional: check state inside loop\n            break\n\nif context_manager.state == context_manager.EXECUTED:\n    print(\"Task completed within timeout.\")\nelif context_manager.state == context_manager.TIMED_OUT:\n    print(\"Task timed out after 5 seconds.\")\n\n# Example using a decorator\n@stopit.threading_timeoutable(default='Timed out!')\ndef potentially_long_function(timeout=1, max_iterations=10**8):\n    print(f\"  Function starting with {timeout}s timeout...\")\n    for i in range(max_iterations):\n        _ = i * 2\n        time.sleep(0.001) # Small sleep to allow thread context switching\n    return \"Function completed.\"\n\nresult = potentially_long_function(timeout=2)\nprint(f\"Decorator result: {result}\")\n\nresult_fast = potentially_long_function(timeout=10, max_iterations=1000)\nprint(f\"Decorator result (fast completion): {result_fast}\")","lang":"python","description":"This quickstart demonstrates using `stopit.ThreadingTimeout` as a context manager and `stopit.threading_timeoutable` as a decorator to limit the execution time of code. The context manager allows checking its state to determine if execution completed or timed out. The decorator automatically returns a default value if the function exceeds its allowed time."},"warnings":[{"fix":"Update your imports and usage to `ThreadingTimeout` and `threading_timeoutable` respectively.","message":"In version 1.1.0, the main context manager `stopit.Timeout` was renamed to `stopit.ThreadingTimeout`, and the decorator `stopit.timeoutable` was renamed to `stopit.threading_timeoutable`. Using the old names will result in import errors or unexpected behavior.","severity":"breaking","affected_versions":"1.0.0 and earlier"},{"fix":"Use the threading-based context managers (`ThreadingTimeout`) and decorators (`threading_timeoutable`) which are platform-independent for basic timeout functionality.","message":"Signal-based timeout controls (`SignalTimeout` and `signal_timeoutable`) are not supported on Windows due to the operating system's lack of `signal.SIGALRM` support.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your application is running on CPython. Be aware that `stopit` might not be suitable for projects requiring broad Python interpreter compatibility.","message":"Threading-based timeout mechanisms (like `ThreadingTimeout`) will only work reliably with CPython implementations. They rely on CPython-specific low-level APIs and are not compatible with alternative Python implementations like PyPy, Jython, or IronPython.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For very precise or immediate interruption of blocking I/O or long `time.sleep` calls, consider using `multiprocessing` to run the task in a separate process that can be terminated.","message":"The library cannot stop the execution of blocking Python atomic instructions that acquire the Global Interpreter Lock (GIL), such as `time.sleep()` for long durations or I/O operations. The asynchronous exception will only be effective *after* such blocking operations complete.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Avoid setting extremely small or zero timeout values. If precise, sub-millisecond control is critical, `stopit` might not be the ideal solution due to Python's GIL and thread scheduling characteristics.","message":"Very short timeout values, especially zero, can lead to unexpected `TimeoutException` being raised immediately or trigger race conditions, particularly on Windows/Cygwin. The accuracy of timeouts generally depends on the GIL interval checking of your Python platform.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Change `stopit.Timeout` to `stopit.ThreadingTimeout`. Similarly, `stopit.timeoutable` should be `stopit.threading_timeoutable`.","cause":"Attempting to use the old class name `Timeout` for the context manager, which was renamed in version 1.1.0.","error":"AttributeError: module 'stopit' has no attribute 'Timeout'"},{"fix":"If the task includes `time.sleep`, break it into smaller sleeps or introduce manual checks for the timeout state. For blocking I/O, consider `multiprocessing` or asynchronous libraries if immediate termination is critical.","cause":"stopit's threading-based timeouts cannot interrupt Python's blocking atomic operations (like `time.sleep` or certain I/O calls) that hold the GIL. The exception is injected only when the GIL is released.","error":"Code inside `with stopit.ThreadingTimeout(...)` block doesn't stop immediately, especially with `time.sleep()`."},{"fix":"Increase the timeout duration slightly or avoid using extremely granular timeout values if possible. If the issue persists, review the context manager's `swallow_exc` parameter or handle the `TimeoutException` gracefully.","cause":"This error can occur unexpectedly even with very small, non-zero timeouts, especially on Windows or when the timeout value is extremely low (e.g., 0.0000000001). It can indicate a race condition in the underlying threading implementation.","error":"stopit.TimeoutException: Timeout"},{"fix":"Ensure any custom exception types you use are properly defined: `class MyTimeoutError(Exception): pass`.","cause":"If you try to catch a custom `TimeoutError` without defining it as an exception class derived from `Exception` (or `BaseException`).","error":"TypeError: exceptions must derive from BaseException"}]}