{"id":7789,"library":"threadloop","title":"Threadloop: Tornado IOLoop Backed Concurrent Futures","description":"Threadloop is a Python library that enables running Tornado coroutines from synchronous Python code by leveraging a thread pool, backed by Tornado's IOLoop. It provides a `ThreadLoopExecutor` that mimics the `concurrent.futures.ThreadPoolExecutor` API. The library is currently at version 1.0.2 and was last updated in 2016, indicating it is no longer actively maintained but generally functional.","status":"maintenance","version":"1.0.2","language":"python","source_language":"en","source_url":"https://github.com/breerly/threadloop","tags":["tornado","asyncio","threading","concurrent-futures","ioloop","concurrency"],"install":[{"cmd":"pip install threadloop","lang":"bash","label":"Install stable release"}],"dependencies":[{"reason":"Core functionality relies on Tornado's IOLoop for managing asynchronous operations. Specifically, `tornado>=4.0.0` is required.","package":"tornado","optional":false}],"imports":[{"wrong":"from threadloop import ThreadLoopExecutor","symbol":"ThreadLoop","correct":"from threadloop import ThreadLoop"}],"quickstart":{"code":"import tornado.gen\nfrom threadloop import ThreadLoopExecutor\n\n@tornado.gen.coroutine\ndef my_coroutine(name):\n    print(f\"Hello from {name} in coroutine!\")\n    yield tornado.gen.sleep(0.1) # Simulate async work\n    print(f\"Goodbye from {name}!\")\n    return f\"Result from {name}\"\n\ndef sync_function(x, y):\n    print(f\"Running sync_function with {x} and {y}\")\n    return x + y\n\nif __name__ == '__main__':\n    # Example 1: Running a Tornado coroutine in the ThreadLoopExecutor\n    with ThreadLoopExecutor() as executor:\n        future_coro = executor.submit(my_coroutine, \"CoroutineWorker\")\n        result_coro = future_coro.result() # Blocks until coroutine completes\n        print(f\"Coroutine result: {result_coro}\")\n\n    # Example 2: Running a regular synchronous function\n    with ThreadLoopExecutor() as executor:\n        future_sync = executor.submit(sync_function, 10, 20)\n        result_sync = future_sync.result()\n        print(f\"Sync function result: {result_sync}\")\n","lang":"python","description":"This quickstart demonstrates how to initialize `ThreadLoopExecutor` as a context manager and submit both Tornado coroutines and regular synchronous functions. The `submit` method returns a future, and `.result()` can be called to block until the task completes and retrieve its return value. Note that `tornado.gen.coroutine` is used for demonstration, which is an older decorator; modern Tornado often uses `async def` functions."},"warnings":[{"fix":"Thoroughly test `threadloop` with your specific Python and Tornado versions. Consider modern alternatives like `concurrent.futures.ThreadPoolExecutor` for general threading or `asyncio` with `loop.run_in_executor` for integrating blocking calls into an event loop for new projects.","message":"The `threadloop` library has not been updated since 2016 (version 1.0.2) and may have compatibility issues with newer Python (3.6+) and Tornado versions. Newer Python versions, especially 3.13+, introduce significant changes to threading (e.g., free-threaded CPython without GIL by default), which might affect `threadloop`'s behavior or performance.","severity":"breaking","affected_versions":"<=1.0.2"},{"fix":"Always retrieve the result or check for exceptions on `Future` objects returned by `submit()` or `map()`. For example, `future.result()` will re-raise any exception that occurred in the worker thread. Alternatively, use `future.add_done_callback(error_handler)` to process results or errors asynchronously.","message":"Tasks submitted to `ThreadLoopExecutor` (or any `concurrent.futures.ThreadPoolExecutor`) can fail silently if their `Future` objects are not inspected (e.g., by calling `.result()`, `.exception()`, or attaching `add_done_callback`). Exceptions raised within submitted tasks will not propagate to the main thread unless explicitly retrieved.","severity":"gotcha","affected_versions":"All"},{"fix":"For CPU-bound parallelism, use `multiprocessing.Pool` or `concurrent.futures.ProcessPoolExecutor` which utilize separate processes, bypassing the GIL. For I/O-bound tasks, threading is generally effective. Be aware that Python 3.13+ with free-threaded builds can offer true parallelism for CPU-bound threaded code.","message":"Python's Global Interpreter Lock (GIL) means that CPU-bound tasks executed within `ThreadLoopExecutor` (which uses threads) will not achieve true parallel execution across multiple CPU cores in standard CPython interpreters (pre-3.13 free-threaded builds). Threads are best for I/O-bound tasks where the GIL is released during blocking operations.","severity":"gotcha","affected_versions":"All (pre-Python 3.13 free-threaded builds)"},{"fix":"Always use `ThreadLoopExecutor` as a context manager (`with ThreadLoopExecutor() as executor:`) to ensure proper shutdown and resource management. If manually managing, ensure `executor.shutdown()` is called only after all tasks have been submitted and you are ready to terminate the pool.","message":"Attempting to submit tasks to a `ThreadLoopExecutor` after it has been shut down will result in a `RuntimeError` or similar exception. This can happen if the executor's lifecycle is not managed correctly, especially when not using it as a context manager.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"search_vec":"'1.0.2':46 '2016':52 'activ':58 'api':39 'asyncio':64 'back':4,26 'code':20 'concurr':5,67,70 'concurrent-futur':66 'concurrent.futures.threadpoolexecutor':38 'coroutin':16 'current':43 'enabl':13 'function':62 'futur':6,68 'general':61 'indic':53 'ioloop':3,30,69 'last':49 'leverag':22 'librari':11,41 'longer':57 'maintain':59 'mimic':36 'pool':25 'provid':32 'python':10,19 'run':14 'synchron':18 'thread':24,65 'threadloop':1,7 'threadloopexecutor':34 'tornado':2,15,28,63 'updat':50 'version':45","created_at":"2026-04-16T14:13:28.073034+00:00","updated_at":"2026-04-16T14:13:28.073034+00:00","problems":null,"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"1.0.2","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/breerly/threadloop","docs":null,"changelog":null,"pypi":"https://pypi.org/project/threadloop/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["http-networking"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-07-03","last_verified":"2026-07-03","next_check":"2026-08-02","install_tag":null}}