{"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":"en","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,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}