Flask - G variable not accessible in multi threaded context - python

I am using ThreadPoolExecutor to create threads in my application. When I try to access the Flask g variable in any of the thread pool tasks, it gives me error
RuntimeError: Working outside of application context.
I tried using app.app_context() as well but it fails with error
AttributeError: '_AppCtxGlobals' object has no attribute 'Test'
Is there anyway I can access the g variable in multi-threaded context?
Sample code to reproduce the issue.
from flask import Flask, g
from concurrent.futures import ThreadPoolExecutor
app = Flask(__name__)
if __name__ == '__main__':
app.run('0.0.0.0', port=8000, debug=False)
#app.before_request
def before_req():
g.Test = 'test'
#app.route("/test", methods=["GET"])
def handle_request():
with ThreadPoolExecutor(max_workers=1) as executor:
response = executor.submit(t1)
var = response.result()
print(var)
def t1():
# with app.app_context():
return g.Test

Related

Flask is not providing a URL

I am a new programmer and I am trying to connect my bot to flask to create a URL for discord.
when I run it, it doesn't do it. Am I missing a line here because it is not coming up with an error but it will not run either.
from threading import Thread
app = Flask ('__code__')
#app.route('/')
def home():
return "Hello. I am alive!"
app.run(host='0.0.0.0',port=5000)
def keep_alive():
t = Thread(target=run)
t.start()
if __name__ == '__code__':
app.run()```
Can someone point me in the right direction? I normally work on python 3.
Thank you
Try running the app when checking the name of your code, not in home() function:
from flask import Flask
from threading import Thread
app = Flask ('__code__')
#app.route('/')
def home():
return "Hello. I am alive!"
def keep_alive():
t = Thread(target=run)
t.start()
if __name__ == '__code__':
app.run(host='0.0.0.0',port=5000)

How can i update global variable outside a thread?

I have a global varibale that share for all of function in my flask socketio server and a thread to start another feature to send notification for which connected to flask socketio server. The thread start from running and the global variable is passed into. The problem is when i change the global varibale outside the thread, it's not updated in the thread.
from flask import Flask, request
from flask_socketio import SocketIO, emit
from flask_cors import CORS, cross_origin
from generate_audio import *
from manage_time import receive_data, clock
from manage_audio import set_audio
import threading
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, cors_allowed_origins="*")
CORS(app)
a = 0
#app.route("/demo", methods=["POST"])
#cross_origin(origin='localhost',headers=['Content-Type','Authorization'])
def receive_request():
global a
a += 1
return "Done"
def clock(a):
while True:
print(a)
if __name__ == "__main__":
global a
threading.Thread(target=clock, args=(a,)).start()
socketio.run(app, port=5000, debug=True, host="0.0.0.0")
How can i update a value inside the thread? It's always equal 0, i want it will be increased everytime i send a request to "/demo".
you can modify global variables like this:
global a
a += 1

Use Flask's "app" singleton to Dask Scheduler/Workers

The Case:
We have some time-consuming functional/integration tests that utilize Flask's current_app for configuration (global variables etc.) and some logging.
We are trying to distribute and parallelize those tests on a cluster (for the moment a local "cluster" created from Dask's Docker image.).
The Issue(s?):
Let's assume the following example:
A time-consuming function:
def will_take_my_time(n)
# Add the 'TAKE_YOUR_TIME' in the config in how many seconds you want
time.sleep(current_app.config['TAKE_YOUR_TIME'])
return n
A time-consuming test:
def need_my_time_test(counter=None):
print(f"Test No. {will_take_my_time(counter)}")
A Flask CLI command that creates a Dask Client to connect to the cluster and execute 10 tests of need_my_time_test:
#app.cli.command()
def itests(extended):
with Client(processes=False) as dask_client:
futures = dask_client.map(need_my_time_test, range(10))
print(f"Futures: {futures}")
print(f"Gathered: {dask_client.gather(futures)}")
EDIT: For convenience let's add an application factory for an easier reproducible example:
def create_app():
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY='dev',
DEBUG=True,
)
#app.route('/hello')
def hello():
return 'Hello, World!'
#app.cli.command()
def itests(extended):
with Client(processes=False) as dask_client:
futures = dask_client.map(need_my_time_test, range(10))
print(f"Futures: {futures}")
print(f"Gathered: {dask_client.gather(futures)}")
Using the above with flask itests, we are running into the following error (described here):
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that
needed to interface with the current application object in some way.
To solve this, set up an application context with app.app_context().
We have tried:
Pushing the app_context (app.app_context().push()) on the app singleton creation.
Using with current_app.app_context(): on the CLI command and some of the functions that use the current_app.
Sending the app_context through a Dask Variable but it cannot serialize the context.
With no avail.
The questions:
Are there any suggestions on what should we try (containing the "where" will be highly appreciated)?
Is there something that we tried correct but misused and we should retry it differently?
When using current_app proxy, it is assumed that the Flask app is created in the same process that the proxy is used.
This is not the situation when tasks submitted to the workers are run.
The tasks are executed isolated away from the Flask app created in the process that submitted the tasks.
In the task, define the flask app and provide the application context there.
import time
from flask import Flask
from dask.distributed import Client
def _create_app():
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY='dev',
DEBUG=True,
TAKE_YOUR_TIME=0.2
)
return app
def will_take_my_time(n):
# Add the 'TAKE_YOUR_TIME' in the config in how many seconds you want
app = _create_app()
with app.app_context():
time.sleep(app.config['TAKE_YOUR_TIME'])
return n
def need_my_time_test(counter=None):
print(f"Test No. {will_take_my_time(counter)}")
def create_app():
app = _create_app()
#app.route('/hello')
def hello():
return 'Hello, World!'
#app.cli.command()
def itests():
with Client(processes=False) as dask_client:
futures = dask_client.map(need_my_time_test, range(10))
print(f"Futures: {futures}")
print(f"Gathered: {dask_client.gather(futures)}")
return app
app = create_app()

Notification from Flask to JS using socket.IO

I'm using the Flask-SocketIO library which works fine but I need to send a notification with emit to the outside of a socket.io decorator and it's a real pain. Looking at the solutions, many people use rabbitmq or redis but I don't know how to use them.
Here's my code :
from flask import Flask, render_template
from flaskwebgui import FlaskUI
from flask_socketio import SocketIO, emit
app = Flask(__name__)
async_mode = None
app.config['SECRET_KEY'] = 'hello'
socketio = SocketIO(app, async_mode=async_mode, message_queue='amqp:///socketio')
def run_sock():
socketio.run(app, debug=True)
ui = FlaskUI(app, fullscreen=True, server=run_sock,)
#app.route("/")
def index():
return render_template('index.html')
#socketio.on('test', namespace='/test')
def test():
print("test")
if __name__ == "__main__":
ui.run()
io = SocketIO(message_queue='amqp:///socketio')
io.emit('test_emit', {'data': 'toto'}, namespace='/test')
My JS front-end never gets the test_emit message, how do I do?
The problem with your emit is that it appears below the ui.run() call, which does not return until you close the application. Move the emit to any function in your application that executes while the server is running (such as a Flask view function) and it should work just fine.
Why do you have two SocketIO objects in the same process? The socketio instance that you defined near the top of the script can be used anywhere within the process, no need to create a second instance. You do not need to use a message queue for this problem, since you have all the usages of Socket.IO within a single process.

Flask-pymongo RuntimeError: Working outside of application context

I'm writing a program to read mongodb document based on id field using flask-pymongo. But I'm getting error, can anybody tell me where am I going wrong?
code:
from flask import Flask, make_response, jsonify
from flask_pymongo import PyMongo
from collections import OrderedDict
from bson import json_util
import json
app = Flask('__name__')
app.config['MONGO_DBNAME'] = 'db_name'
app.config['MONGO_URI'] = 'mongodb://192.168.55.24:27017/db_name'
mongo_connection = PyMongo(app)
#app.route('/')
def index(inp_id):
collection = mongo_connection.db.table_name
one_record = collection.find_one({'id': inp_id})
obj_str = json_util.dumps(one_record)
obj_dict = json.loads(obj_str, object_hook=OrderedDict)
return make_response(jsonify(obj_dict), 200)
if __name__ == '__main__':
index('5cd00a468b36db516b6d2f16') # I think this is where I'm going wrong
giving me the below error:
RuntimeError: Working outside of application context.
If I pass id value directly in the place of inp_id I get the result but I'm trying to write a generic one.
Flask has an application context, You might need to use app.app_context() to make it work.
The application context keeps track of the application-level data
during a request, CLI command, or other activity. Rather than passing
the application around to each function, the current_app and g proxies
are accessed instead.
Try this :
def index(inp_id):
with app.app_context():
collection = mongo_connection.db.table_name
one_record = collection.find_one({'id': inp_id})
obj_str = json_util.dumps(one_record)
obj_dict = json.loads(obj_str, object_hook=OrderedDict)
return make_response(jsonify(obj_dict), 200)
For more information, read Flask Application context

Categories