{"id":4014,"library":"flask-threads","title":"Flask-Threads","description":"Flask-Threads is a helper library designed to simplify working with threads within Flask applications. It addresses the common challenge of maintaining the Flask application context (e.g., `flask.g`, `request`) when executing code in background threads or using concurrent futures, which are typically thread-local. The library ensures that thread-local proxies remain accessible, preventing `RuntimeError` exceptions that occur when trying to access context outside the main request thread. The current version is 0.2.0, released on May 20, 2025, with an infrequent release cadence, primarily focusing on Flask compatibility.","status":"active","version":"0.2.0","language":"python","source_language":"en","source_url":"https://github.com/sintezcs/flask-threads.git","tags":["flask","threading","concurrency","context","background-tasks","app-context"],"install":[{"cmd":"pip install Flask-Threads","lang":"bash","label":"Install with pip"}],"dependencies":[{"reason":"Core dependency for integration with Flask applications. Compatibility fixed for Flask >= 3.0.0.","package":"Flask"}],"imports":[{"symbol":"AppContextThread","correct":"from flaskthreads import AppContextThread"},{"symbol":"ThreadPoolWithAppContextExecutor","correct":"from flaskthreads import ThreadPoolWithAppContextExecutor"}],"quickstart":{"code":"from flask import g, request, Flask\nfrom flaskthreads import AppContextThread, ThreadPoolWithAppContextExecutor\nimport time\n\napp = Flask('my_app')\n\ndef do_some_user_work_in_another_thread():\n    # Accessing flask.g from a different thread, enabled by Flask-Threads\n    user_id = g.user_id\n    print(f\"[Thread] User ID from g: {user_id}\")\n    time.sleep(1) # Simulate work\n    return f\"Processed user {user_id}\"\n\n@app.route('/user/thread')\ndef get_user_with_thread():\n    g.user_id = request.headers.get('user-id', 'default_user_id_thread')\n    print(f\"[Main] Setting g.user_id: {g.user_id}\")\n\n    t = AppContextThread(target=do_some_user_work_in_another_thread)\n    t.start()\n    t.join() # Wait for the thread to complete\n    return 'OK via AppContextThread'\n\n@app.route('/user/executor')\ndef get_user_with_executor():\n    g.user_id = request.headers.get('user-id', 'default_user_id_executor')\n    print(f\"[Main] Setting g.user_id: {g.user_id}\")\n\n    with ThreadPoolWithAppContextExecutor(max_workers=2) as pool:\n        future = pool.submit(do_some_user_work_in_another_thread)\n        result = future.result() # Wait for the future to complete\n        print(f\"[Main] Future result: {result}\")\n    return 'OK via ThreadPoolWithAppContextExecutor'\n\nif __name__ == '__main__':\n    # For demonstration, use a simple run. In production, use a WSGI server.\n    # Set 'user-id' header (e.g., with curl -H 'user-id: 123' http://127.0.0.1:5000/user/thread)\n    app.run(debug=True, use_reloader=False) # use_reloader=False to avoid double thread start in dev","lang":"python","description":"This example demonstrates how to use `AppContextThread` and `ThreadPoolWithAppContextExecutor` to run background tasks while retaining access to Flask's application context, specifically `flask.g`. The `user-id` is set in `flask.g` within the main request thread and then accessed correctly by the function running in a separate thread."},"warnings":[{"fix":"Upgrade to Flask-Threads version 0.2.0 or newer: `pip install --upgrade Flask-Threads`. Ensure your Flask version is compatible.","message":"Older versions of Flask-Threads might not be compatible with Flask versions 3.0.0 and above.","severity":"breaking","affected_versions":"<0.2.0"},{"fix":"To prevent this in development, run your Flask application with `app.run(debug=True, use_reloader=False)`. For production, use a WSGI server like Gunicorn or uWSGI, which manage processes differently and typically don't have this issue.","message":"When running Flask in development mode with `debug=True`, Flask's reloader often starts the application twice. This can lead to background threads (including those managed by Flask-Threads) being initialized and run twice, causing unexpected behavior.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Only access context-local objects in background threads for read-only purposes or when `flask-threads` explicitly manages the context copy. For complex, long-running background jobs, consider external task queues like Celery or RQ, and pass only plain, serializable data (like IDs or file paths) rather than Flask context objects.","message":"While Flask-Threads helps maintain application context in background threads, it's crucial to understand that Flask's `request`, `g`, and `session` proxies are fundamentally tied to a specific request's lifecycle and thread. Misusing them (e.g., trying to modify `request` state in a background thread or keeping the context alive unnecessarily long) can still lead to data leaks, errors, or unexpected behavior.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For CPU-bound tasks, consider using multi-processing (e.g., Python's `multiprocessing` module or `concurrent.futures.ProcessPoolExecutor`), or dedicated worker queues, which can leverage multiple CPU cores.","message":"Python's Global Interpreter Lock (GIL) limits true CPU parallelism for threads. While `flask-threads` is excellent for I/O-bound tasks that need Flask context, it will not make CPU-bound tasks run faster by simply using more threads.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"search_vec":"'0.2.0':79 '20':83 '2025':84 'access':59,68 'address':21 'app':103 'app-context':102 'applic':19,29 'background':38,100 'background-task':99 'cadenc':89 'challeng':24 'code':36 'common':23 'compat':94 'concurr':42,97 'context':30,69,98,104 'current':76 'design':11 'e.g':31 'ensur':52 'except':62 'execut':35 'flask':2,5,18,28,93,95 'flask-thread':1,4 'flask.g':32 'focus':91 'futur':43 'helper':9 'infrequ':87 'librari':10,51 'local':49,56 'main':72 'maintain':26 'may':82 'occur':64 'outsid':70 'prevent':60 'primarili':90 'proxi':57 'releas':80,88 'remain':58 'request':33,73 'runtimeerror':61 'simplifi':13 'task':101 'thread':3,6,16,39,48,55,74,96 'thread-loc':47,54 'tri':66 'typic':46 'use':41 'version':77 'within':17 'work':14","created_at":"2026-04-12T03:37:19.352391+00:00","updated_at":"2026-04-16T15:08:36.893605+00:00","problems":[{"fix":"Wrap the code that accesses application context in the background thread with `app.app_context()` or use `flask-threads`'s `AppContextThread` or `ThreadPoolWithAppContextExecutor` to automatically manage the context. For example: `from flaskthreads import AppContextThread; t = AppContextThread(target=my_function, args=(app,)).start()`","cause":"This error occurs when you try to access Flask's application-level objects (like `current_app` or extensions) in a background thread without an active application context. Flask's contexts are thread-local, so a new thread does not automatically inherit the context from the main request thread.","error":"RuntimeError: Working outside of application context."},{"fix":"Use `flask-threads`'s `AppContextThread` or `ThreadPoolWithAppContextExecutor`, which ensure that the request context from the original thread is properly propagated to the background thread. Alternatively, pass necessary data extracted from `request` or `g` as arguments to your background function, avoiding direct context access in the thread.","cause":"This error arises when you attempt to use request-specific objects (like `request`, `session`, or `g`) in a background thread, as the request context is thread-local and is not automatically available in the new thread after the original request has ended or in a separate thread.","error":"RuntimeError: Working outside of request context."},{"fix":"Ensure the library is installed in your active Python environment using `pip install Flask-Threads`. Double-check your import statement for typos, e.g., `from flaskthreads import AppContextThread`.","cause":"This error means the Python interpreter cannot find the `flaskthreads` library, most commonly because it hasn't been installed, or there's a typo in the import statement, or it's installed in a different Python environment than the one being used.","error":"ModuleNotFoundError: No module named 'flaskthreads'"},{"fix":"When you need the actual application object from within a context, use `current_app._get_current_object()`. When passing the application to a background thread, if not using `flask-threads`, ensure you pass the actual application instance (`app`) or handle the context explicitly within the thread using `app.app_context()`.","cause":"This error typically occurs when developers attempt to manually dereference a Flask context local proxy (like `current_app` or `request`) by calling `_get_current_object()` directly on a `Flask` application instance (e.g., `app._get_current_object()`) instead of the proxy itself (e.g., `current_app._get_current_object()`). The `_get_current_object()` method is part of the `LocalProxy` object (which `current_app` is), not the `Flask` application object directly.","error":"AttributeError: 'Flask' object has no attribute '_get_current_object'"}],"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.2.0","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/sintezcs/flask-threads.git","docs":null,"changelog":null,"pypi":"https://pypi.org/project/flask-threads/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["web-framework"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-08-29","next_check":"2026-07-28","install_tag":null}}