I'm trying to deploy my Flask app to Apache webserver.
In my main file, before running the Flask app, I start a daemon thread that runs in background:
# ... here there are all the imports and the Flaks routes
def main():
x = threading.Thread(target=my_thread_function)
x.daemon = True
x.start()
# app.run() # I moved this line below
x.join()
if __name__ == '__main__':
main()
app.run()
This is my wsgi file:
import sys
sys.path.insert(0, 'C:\\myapp\\')
from myapp import app as application
If I run Apache server, Flask works fine and I can see the web app interface when I connect to the IP address. However, the background thread doesn't work, because I don't see its "effect" in the app.
If I run the same code with the Flask development server, the background thread works fine.
How can it work with Apache?
remove the join() because it will block the app.run()
# ... here there are all the imports and the Flaks routes
def main():
x = threading.Thread(target=my_thread_function)
x.daemon = True
x.start()
if __name__ == '__main__':
main()
app.run()
Related
This question already has answers here:
Run code after flask application has started
(7 answers)
Closed last year.
I have a flask application and I would like to run it in a "production" way using uwsgi.
I have my launcher.py:
from app import app
import db
if __name__ == "__main__":
db.init()
app.run()
If I run the application with simply python launcher.py it's all ok. Especially, the db.init() is called correctly.
However, if I run using uwgsi with uwsgi app.ini , db.init() is not called.
Here is app.ini:
[uwsgi]
wsgi-file = launcher.py
callable = app
socket = :8080
I'm new with flask and uwsgi so probably I missed something but I could not find the solution in the different tutorials I read.
Also, in case you need it to understand the project, here is app.py:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def index():
return "hello from flask"
if __name__ == "__main__":
db.init()
app.run()
All files are in the same level in my project:
webserver/
- app.ini
- launcher.py
- app.py
- db.py
So, what am I doing wrong here?
Your code under if __name__ == "__main__": is not executed because uwsgi does not run your script like python app.py. Instead it imports the module specified in wsgi-file and looks for an object specified as callable (app in our case). You can test it by using the following script:
from flask import Flask
app = Flask(__name__)
print(__name__)
if __name__ == '__main__':
app.run()
If you run it with python ./flask_app.py then the output will be
$ python ./flask_app.py
__main__
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
(notice __main__ - it means we're running the script). However if you run it with uwsgi the __name__ will be app (it will be the name of your file, so app in my case):
$ uwsgi --http 127.0.0.1:5000 --module app:app
...
*** Operational MODE: single process ***
app
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7fb2d0c067b0 pid: 46794 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 46794, cores: 1)
Similar output will be if you run your app with FLASK_APP=app flask run - it does not execute script, it just imports it and uses app object from it.
So, in order to initialize database you should either move your db initialization out of if __name__ == "__main__":
from flask import Flask
app = Flask(__name__)
class DB:
def init(self):
self.data = 'Hello, World'
db = DB()
#app.route("/")
def hello_world():
return db.data
db.init()
if __name__ == '__main__':
app.run()
Or add a before_first_request handler:
# replace db.init() with
#app.before_first_request
def init_db():
db.init()
Notice the difference between them - if you put db.init() as a top-level statement it will be executed once you load app.py. If you register a before_first_request callback it will be executed once first request arrives to your application. Pick the one that works best for you.
The following scenario:
I have a Raspberry Pi running as a server. Currently I am using a Python script with Flask and I can also access the Raspberry Pi from my PC. (The flask server runs an react app.)
But the function should be extended. It should look like the following:
2nd Python script is running all the time. This Python script fetches data from an external API every second and processes it. If certain conditions are met, the data should be processed and then the data should be communicated to the Python Flask server. And the Flask server then forwards the data to the website running on the computer.
How or which method is best to program this "interprocess communication". Are there any libraries? I tried Celery, but then it throws up my second Python script whenever I want to access the external API, so I don't know if this is the right choice.
What else would be the best approach? Threading? Direct interprocess communication?
If important, this is how my server application looks so far:
from gevent import monkey
from flask import Flask, render_template
from flask_socketio import SocketIO
monkey.patch_all()
app = Flask(__name__, template_folder='./build', static_folder='./build/static')
socket_io = SocketIO(app)
#app.route('/')
def main():
return render_template('index.html')
#socket_io.on('fromFrontend')
def handleInput(input):
print('Input from Frontend: ' + input)
send_time()
#socket_io.on('time')
def send_time():
socket_io.emit('time', {'returnTime': "some time"})
if __name__ == '__main__':
socket_io.run(app, host='0.0.0.0', port=5000, debug=True)
Well i found a solution for my specific problem i implemented it with a thread as follows:
import gevent.monkey
gevent.monkey.patch_all()
from flask import Flask, render_template
from flask_socketio import SocketIO
import time
import requests
from threading import Thread
app = Flask(__name__, template_folder='./build', static_folder='./build/static')
socket_io = SocketIO(app)
#app.route('/')
def main():
thread = Thread(target=backgroundTask)
thread.daemon = True
thread.start()
return render_template('index.html')
#socket_io.on('fromFrontend')
def handleInput(input):
print('Input from Frontend: ' + input)
#socket_io.on('time')
def send_time():
socket_io.emit('time', {'returnTime': 'hi frontend'})
def backgroundTask():
# do something here
# access socket to push some data
socket_io.emit('time', {'returnTime': "some time"})
if __name__ == '__main__':
socket_io.run(app, host='0.0.0.0', port=5000, debug=True)
I am trying to run flask app and webview simultaneously but it seems that only flask app is running first and blocking the webview to open it.
if __name__ == '__main__':
os.system('python app.py')
webview.create_window('Hello world', 'http://127.0.0.1:5000/')
webview.start()
Webview command is only initiated once I close the flask server (Ctr+C) but till then webview returns connection refused.
You need to run your flask app in the background. Here is a sample working example. os.system('python app.py &')
main.py
import webview
import os
if __name__ == '__main__':
os.system('python app.py &')
webview.create_window('Hello world', 'http://127.0.0.1:5000/')
webview.start()
app.py
# Importing flask module in the project is mandatory
# An object of Flask class is our WSGI application.
from flask import Flask
# Flask constructor takes the name of
# current module (__name__) as argument.
app = Flask(__name__)
# The route() function of the Flask class is a decorator,
# which tells the application which URL should call
# the associated function.
#app.route('/')
# ‘/’ URL is bound with hello_world() function.
def hello_world():
return 'Hello World'
# main driver function
if __name__ == '__main__':
# run() method of Flask class runs the application
# on the local development server.
app.run()
I am trying to setup a Flask app that will run a shell script when it receives a request. The purpose of this is to re-deploy another app when I push to GitLab. I have everything connected, but for some reason the subprocess spawned by the Flask app gets terminated shortly after it starts. I've been logging into my server over SSH to start the Flask app, and everything works fine as long as I stay logged in, but once I kill the session it stops working.
Flask app
from flask import Flask, request, abort, Response
import os
import subprocess
from waitress import serve
process:subprocess.Popen = None
app = Flask(__name__)
#app.route('/', methods = ['POST'])
def deploy():
req_secret = request.headers.get("X-Gitlab-Token")
if req_secret is not None:
if 'DEPLOY_SECRET' in os.environ:
if os.environ['DEPLOY_SECRET'] == req_secret:
global process
if process is not None:
process.terminate()
process = subprocess.Popen("./deploy.sh", stdout=subprocess.PIPE, shell=True)
return 'Success'
abort(401)
if __name__ == "__main__":
serve(app, port=5000)
deploy.sh
#!/bin/sh
killall server
cd ..
git pull origin master
diesel migration run
cargo run
run.sh
#!/bin/sh
DEPLOY_SECRET=$1 pipenv run python autodeploy.py
cargo run should run forever, and it does as long as I stay logged into my SSH session. I start the flask app by running ./run &
Maybe your waitress server has no privileges to run your scripts. Try to change onwership to your scripts to 'waitress_user' like:
chown your_waitress_user deploy.sh
I am not sure for the username, probably would be 'waitress'.
Turns out the solution was to use nohup in the python script
from flask import Flask, request, abort, Response
import os
import subprocess
from waitress import serve
process:subprocess.Popen = None
app = Flask(__name__)
#app.route('/', methods = ['POST'])
def deploy():
req_secret = request.headers.get("X-Gitlab-Token")
if req_secret is not None:
if 'DEPLOY_SECRET' in os.environ:
if os.environ['DEPLOY_SECRET'] == req_secret:
global process
if process is not None:
process.terminate()
with open("autodeploy.log", "a+") as log_file:
process = subprocess.Popen(["nohup", "./deploy.sh"], stdout=log_file, stderr=log_file)
return 'Success'
abort(401)
if __name__ == "__main__":
serve(app, port=5000)
I have a bottle web server running with UWSGI and Nginx. Normally, if I start the script manually with
python app.py
I'm able to do
if __name__ == '__main__':
spawn_workers()
init_workspace()
run(app, host='0.0.0.0', port=8080)
the issue is, when using UWSGI, is that it doesn't run the if __name__ == '__main__' part, because it just grabs the app = application = bottle.Bottle() part. This means I never have a chance to spawn background workers before the webserver is started.
What's the proper way around this? I see that flask has a app.before_first_request function, but I couldn't find anything that corresponds to that feature for bottle.
Is it not sufficient to just perform your initialization in app.py? E.g.,
# app.py
spawn_workers()
init_workspace()
app = Bottle()