14

I'm writing a python/flask application and would like to add the functionality of reloading the server.

I'm currently running the server with the following option

app.run(debug=True)

which results in the following, each time a code change happens

* Running on http://127.0.0.1:5000/
* Restarting with reloader

In a production environment however, I would rather not have debug=True set, but be able to only reload the application server whenever I need to.

I'm trying to get two things working:

  1. if reload_needed: reload_server(), and
  2. if a user clicks on a "Reload Server" button in the admin panel, the reload_server() function should be called.

However, despite the fact that the server get's reloaded after code changes, I couldn't find a function that let's me do exactly that.

If possible I would like to use the flask/werkzeug internal capabilities. I am aware that I could achieve something like that by adding things like gunicorn/nginx/apache, etc.

Falko
  • 17,076
  • 13
  • 60
  • 105
mohrphium
  • 353
  • 1
  • 4
  • 13
  • 2
    Looks like the relevant capabilities of werkzeug, e.g https://github.com/mitsuhiko/werkzeug/blob/f9d0f4e74a78848740c53d7d7256487aa81a1be8/werkzeug/_reloader.py , are deeply hard-coded to watch the filesystem for changes (directly or via `os.stat`) to trigger a reload. I think you'll need to modify _reloader.py and offer the patch to werkzeug's authors in order to enable reloading via non-filesystem triggers. – Alex Martelli Dec 31 '14 at 16:21
  • This should work: [An example on how to reload Flask app in runtime](https://gist.github.com/nguyenkims/ff0c0c52b6a15ddd16832c562f2cae1d) – Evandro Coan Oct 02 '19 at 15:44

2 Answers2

6

I think I've had the same problem.

So there was a python/flask application (XY.py), on clients. I wrote a build step (Teamcity) which deploys this python code to the clients. Let's suppose the XY.py is already running on the clients. After deploying this new/fixed/corrected XY.py I had to restart it for applying the changes on the running code.

The problem what I've had is that after using the fine restarting oneliner os.execl(sys.executable, *([sys.executable]+sys.argv)) my port used by app is still busy/established, so after restarting I can't reach it.

This is how I resolved the problem: I put my app to run on a separate Process and made a queue for it. To see it more cleanly here is some code.

global some_queue = None

@app.route('/restart')
def restart():
   try:
     some_queue.put("something")
     return "Quit"

def start_flaskapp(queue):
   some_queue = queue
   app.run(your_parameters)

Add this to your main:

q = Queue()
p = Process(target=start_flaskapp, args=[q,])
p.start()
while True: #wathing queue, sleep if there is no call, otherwise break
   if q.empty(): 
        time.sleep(1)
   else:
      break
p.terminate() #terminate flaskapp and then restart the app on subprocess
args = [sys.executable] + [sys.argv[0]]
subprocess.call(args)

Hope it was clean and short enough and it helped to you!

Falko
  • 17,076
  • 13
  • 60
  • 105
tamasbalassa
  • 61
  • 1
  • 4
3

How following in your Python code in order to kill the server:

@app.route('/quit')
def _quit():
    os._exit(0)

When process is killed it will repeat itself in the while loop.

app_run.sh:

#!/bin/bash

while true
do
    hypercorn app_async:app -b 0.0.0.0:5000 
    sleep 1
done
alper
  • 2,919
  • 9
  • 53
  • 102