I'm playing with Flask a little, for my application I would require a global storage which is updated by a Thread running in the background on the server. I found this question about global context and the answer from Johan Gov seems to work if I init the server using /create explicitly:
from flask import Flask
from flask.json import jsonify
app = Flask(__name__)
cache = {}
#app.route("/create")
def create():
cache['foo'] = 0
return jsonify(cache['foo'])
#app.route("/increment")
def increment():
cache['foo'] = cache['foo'] + 1
return jsonify(cache['foo'])
#app.route("/read")
def read():
return jsonify(cache['foo'])
if __name__ == '__main__':
app.run()
If I try to call the init automaticaly however, it fails as apparently no cache["foo"] is known.
from flask import Flask
from flask.json import jsonify
app = Flask(__name__)
cache = {}
def create(): #create does not have a route anymore
cache['foo'] = 0
#app.route("/increment")
def increment():
cache['foo'] = cache['foo'] + 1
return jsonify(cache['foo'])
#app.route("/read")
def read():
return jsonify(cache['foo'])
if __name__ == '__main__':
create() #initialize by default
app.run()
Why is this happening? How can I initialize global state before starting the Application?
You can use the Cache as your app property, i always use this when i want to avoid awkward global definitions, just define the cache like this:
# here u create a "cache" attribute for the app.
app.cache = {}
app.cache['foo'] = 0
# then after that when calling in a route:
# notice that we don't need the global keyword since we are using the app.
#app.route("/increment")
def increment():
app.cache = app.cache + 1
return jsonify(app.cache)
I even used relatively big objects like deep learning models using this method and had not problems at all.
tbh, the above code work for me without any change and I'm able to read and increment counter.
Try below code with global variable
from flask import Flask
from flask.json import jsonify
app = Flask(__name__)
cache = {}
def create(): # create does not have a route anymore
global cache
cache['foo'] = 0
#app.route("/increment")
def increment():
global cache
cache['foo'] = cache['foo'] + 1
return jsonify(cache['foo'])
#app.route("/read")
def read():
return jsonify(cache['foo'])
if __name__ == '__main__':
create() # initialize by default
app.run()
Related
I would like to run an infinite loop in flask, which do something with a global list.
I'd like to append the list through an API call, and process data from the updated list.
What is the problem?
Usage: you run flask application, and call localhost:5000/ to append the list.
It will return the new list, but in the loop, it remains the initial list.
Thanks
import time
from flask import Flask
from multiprocessing import Process, Value
app = Flask(__name__)
stuff = [1, 2]
#app.route('/', methods=['GET'])
def index():
global stuff
stuff.append(max(stuff) + 1)
print('in request, stuff: ', stuff)
return ', '.join(map(str, stuff))
def print_stuff():
global stuff
print('in loop, stuff: ', stuff)
def record_loop(loop_on):
while True:
if loop_on.value == True:
print_stuff()
time.sleep(1)
if __name__ == "__main__":
recording_on = Value('b', True)
p = Process(target=record_loop, args=(recording_on,))
p.start()
app.run(debug=True, use_reloader=False)
p.join()
I found the working solution:
import time
from flask import Flask
from flask_apscheduler import APScheduler
app = Flask(__name__)
scheduler = APScheduler()
i = 0
def scheduleTask():
global i
print("This test runs every 1 seconds", i)
time.sleep(2)
#app.route('/')
def hello():
global i
i += 1
return str(i)
if __name__ == '__main__':
scheduler.add_job(id = 'Scheduled Task', func=scheduleTask, trigger="interval", seconds=1)
scheduler.start()
app.run(host="0.0.0.0")
I am trying to create a variable that I can retrieve outside of the function counts every time a chalice webhook alert is triggered. I cannot figure out how to get the variable out of the function. Here is my code. Thank you!
from chalice import Chalice
app = Chalice(app_name='tv_alert')
counter = None
#app.route('/')
def index():
return {'hello': 'world'}
#app.route('/tv', methods=['POST'])
def tv():
request = app.current_request
webhook_message = request.json_body
if webhook_message != 0:
counter += 1
return {
'message': 'I received the webhook notification!',
'webhook_message': webhook_message
}
print(counter)
I have a basic flask API running :
u/app.route('/helloworld', methods = ['GET'])
def first_api():
hname = "hello"
lhname = "world"
print(hname+lhanme)
Now I need to add some unit tests to it, and here is my unit test file:
import json
def test_index(app, client):
res = client.get('/helloworld')
assert res.status_code == 200
assert "hello" in res.data
How can I pass value for variables hname and lhname from this unit test?
Here is my conf file for pytest:
import pytest
from app import app as flask_app
u/pytest.fixture
def app():
return flask_app
u/pytest.fixture
def client(app):
return app.test_client()
You have a little mistake in your endpoint. You want it to return the string instead of printing it. Please consider the following example:
from flask import Flask, request
flask_app = Flask(__name__)
app = flask_app
#app.route('/helloworld', methods = ['GET'])
def first_api():
hname = request.args.get("hname")
lhname = request.args.get("lname")
print(hname)
return hname + lhname
def test_index(app):
client = app.test_client()
hname = "hello"
lname = "world"
res = client.get('/helloworld?hname={}&lname={}'.format(hname, lname))
assert res.status_code == 200
assert "hello" in res.data.decode("UTF-8")
if __name__ == "__main__":
test_index(app)
This question already has answers here:
Are global variables thread-safe in Flask? How do I share data between requests?
(4 answers)
Closed 4 years ago.
I have a problem with the global variable in Flask.
from flask import Flask, redirect
app = Flask(__name__)
#app.route('/')
def define_x():
global x
x = 10
return redirect('/test')
#app.route('/test')
def test_x():
return str(x)
if __name__ == '__main__':
app.run()
There is an error when url redirect:
NameError: global name 'x' is not defined
But if I define 'x' on the top of the function:
from flask import Flask, redirect
app = Flask(__name__)
x = None
#app.route('/')
def define_x():
global x
x = 10
return redirect('/test')
#app.route('/test')
def test_x():
return str(x)
if __name__ == '__main__':
app.run()
the redirect page return None not 10.
Just add
x = None
at top of script
I want to create multiple threads and every one of them should create flask app.
I am not sure how to do it, but that's what I have:
app = Flask(__name__)
app.url_map.strict_slashes = False
#app.route('/api/v1/something/<string:FirstArgument>/<string:SecondArgument>/', methods=['POST'])
def do_it(FirstArgument, SecondArgument):
request_str = request.get_data().decode('utf-8').strip()
response = somefunction(mydata.state, request_str)
return response, 200
def run_app(this_port, mydata):
currentThread = threading.current_thread()
mydata.state = some_function_that_returns_6GB_of_data()
app.run(host='0.0.0.0',port=this_port)
if __name__ == '__main__':
mydata = threading.local()
thread1 = Thread(target=run_app, args=(4100, mydata,))
#thread2 = Thread(target=run_app, args=(4101,mydata,))
thread1.start()
#thread2.start()
For now I want to test only one thread. And I don't know how to pass mydata.state to the 'do_it'. If I add new argument (def do_it(FirstArgument, SecondArgument, mydata.state)) than Flask says that he wants to get this variable from the app.route. How can I pass this data to the do_it function?
And one more question. This program will pas N instances of state to N threads on N ports?
Or I should do something like this:
def do_it(FirstArgument, SecondArgument):
request_str = request.get_data().decode('utf-8').strip()
response = somefunction(mydata.state[threading.get_ident()], request_str)
return response, 200
def run_app(this_port, mydata):
currentThread = threading.current_thread()
mydata.state[threading.get_ident()] = some_function_that_returns_6GB_of_data()
app.run(host='0.0.0.0',port=this_port)