How to run flask server from another module? - python

I am trying to run a flask server from another module and then close the server (it's not the main point of the application), currently the code looks like this for webserver.py
from flask import Flask, render_template
from flask_classful import FlaskView
import os
from werkzeug.utils import secure_filename
from flask import request
host = 'localhost'
debug = True
app = Flask (__name__)
app.config
#app.route('/')
def main():
return render_template("index.html")
def run():
if __name__ == 'Refactor2':
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
def shutdown_server():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
def shutdownServer():
shutdown_server()
return "Server is shutting down"
I am then trying to run this in the following module (named Refactor2):
import webserver
class buyer:
def __init__(self, email, password):
self.email = email
self.password = password
def server_run(self):
run()
print("Server has been started")
However, the server does not run and I cannot navigate to the webpage. There are no error messages shown.

Seems like an unusual way to launch a Flask app, but with that aside...
Assuming you're running this with python Refactor2.py, __name__ will be 'webserver'.
This can be demonstrated with a minimal example:
$ cat webserver.py
def run():
print (__name__)
$ cat Refactor2.py
import webserver
webserver.run()
$ python Refactor2.py
webserver
So in your webserver module you could do do:
def run():
if __name__ == 'webserver':
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
Or just:
def run():
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
And call it like:
import webserver
# ...
class buyer:
# ...
def server_run(self):
webserver.run()
print("Server has been started")
Of course, that 'Server has been started' won't actually be reached until the server (the webserver.run call) has completed and the server has stopped.
Again, this seems like an odd way to launch an application. I suggest you investigate the docs on how to run Flask in production, as it seems what you're trying to acheive is the job of an orchestration system, and not the python process itself. In a production env, you should use a WSGI server like gunicorn, instead of the dev server (app.run). Granted, perhaps you know this already ;)

__name__ gives the name of the current module. So in your run() method __name__ is probably resolving to webserver. I'd suggest passing the name as a variable to run() from server_run()
webserver.py
def run(name):
if name == 'Refactor2':
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
Refactor2
import webserver
class buyer:
def __init__(self, email, password):
self.email = email
self.password = password
def server_run(self):
run(__name__)
print("Server has been started")
Note that if Refactor2 is in a package you might get a dotted module name, like 'src.Refactor2'. It might be better to pass a more explicit name to run, as if you rename Refactor2 you'll need to update your hardcode in webserver.py too. Something like
def server_run(self):
webserver.run('buyer')
print("Server has been started")
and
(webserver.py)
def run(name):
if name == 'buyer':
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
edit: not sure if you provided a full code example, but it also looks like maybe you're not calling the right run() method in server_run() - it looks like it should be called on the webserver module, which I edited my answer to reflect

Related

Flask Web server App on Window Python program is not able to shutdown on program exist

I have python version 3.9, I am using the default development web server that is provided by the flask on windows OS (laptop). I need to run the app on Windows machine, and it should be able to start and stop the app on demand.
Here is what I tried so far. when I run the application either in VS code, I need to force stop the app, If running in the command windows I have to kill the python app from task manager.
With the following code changes I can exit the app by sending the SIGTERM to proess itself, as both the Flask, and simplehttpserver do not provide an API for exiting the process.
from flask import Flask, request, g, make_response
import queue
import time
import os
from threading import Thread
import signal
import ctypes
from multiprocessing import Process
import sys
OUTPUT_EMPTY_LIMIT = 3
DEFAULT_PORT = 9090
SHUTDOWN = False
EXIT_CHARS = "Qq\x11\x18" # 'Q', 'q', Ctrl-Q, ESC
print("Name = {}".format(__name__))
app = Flask(__name__)
def shutdown_app():
global SHUTDOWN
SHUTDOWN = True
#app.before_request
def before_request():
if SHUTDOWN:
return 'Shutting down...'
def run_app(port, host, debug, threaded):
app.run(port=port, host=host, debug=debug, threaded=threaded)
#app.route("/")
def app_help():
return "Hello, World from help!"
#app.route("/square/<int:number>")
def square(number):
return str(number**2)
# This doesnt kill the app as well.
#app.route("/stop")
def stop():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the werkzeug Server')
func()
return 'Server shutting down...'
exit(0)
if __name__ == "__main__":
port = 5000
host = '0.0.0.0'
debug = False
threaded = True
process = Process(target=run_app, args=(port, host, debug, threaded))
process.start()
while True:
ch = input("Enter 'Q' to stop server and exit: ")
if (ch == 'Q'):
break
shutdown_app()
process.terminate()
#process.kill()
#process.join()
print("Exiting the app")
# os.kill(os.getpid(), signal.SIGINT)
os._exit(0)
I am new to Python and have tried both google search and chatGPT to find a way to shutdown Flask App and the web server that is started on a windows operating system.
I have also tried the other answeres on the stack overflow 15562446
I also tried the link Shutdown The Simple Server
I've found while testing that werkzeug.server.shutdown does nothing, and it needs to be shutdown using sys.exit(0) on my windows machine.
In your code a value is returned before the exit() is run - therefore it does not shut down. One way to do what you want is using deferred callbacks.
from flask import after_this_request
#app.get('/stop')
def shutdown():
#after_this_request
def response_processor(response):
#response.call_on_close
def shutdown():
import sys
sys.exit("Stop API Called")
return response
return 'Server shutting down...',200

Add Tensorboard server to Flask endpoint

I have a Flask App and a Tensorboad server. Is there a way by which I can map the Tensorboard server to one of the endpoints of Flask so that as soon as I hit that endpoint it triggers the Tensorboard server?
Flask application
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route('/hello-world', methods=['GET', 'POST'])
def say_hello():
return jsonify({'result': 'Hello world'})
if __name__ == "__main__":
app.run(host=host, port=5000)
Tensorboard server code:
from tensorboard.program import TensorBoard, setup_environment
def tensorboard_main(host, port, logdir):
configuration = list([""])
configuration.extend(["--host", host])
configuration.extend(["--port", port])
configuration.extend(["--logdir", logdir])
tensorboard = TensorBoard()
tensorboard.configure(configuration)
tensorboard.main()
if __name__ == "__main__":
host = "0.0.0.0"
port = "7070"
logdir = '/tmp/logdir'
tensorboard_main(host, port, logdir)
I tried creating an endpoint in Flask app and then added tensorboard_main(host, port, logdir) in the hope that if I hit the endpoint then the server will start but I got no luck.
I found out that to integrate a TensorBoard server into a larger Flask app, the best way would be to compose the applications at the WSGI level.
The tensorboard.program API allows us to pass a custom server
class. The signature here is that server_class should be a callable which takes the TensorBoard WSGI app and returns a server that satisfies the TensorBoardServer interface.
Hence the code is:
import os
import flask
import tensorboard as tb
from werkzeug import serving
from werkzeug.middleware import dispatcher
HOST = "0.0.0.0"
PORT = 7070
flask_app = flask.Flask(__name__)
#flask_app.route("/hello-world", methods=["GET", "POST"])
def say_hello():
return flask.jsonify({"result": "Hello world"})
class CustomServer(tb.program.TensorBoardServer):
def __init__(self, tensorboard_app, flags):
del flags # unused
self._app = dispatcher.DispatcherMiddleware(
flask_app, {"/tensorboard": tensorboard_app}
)
def serve_forever(self):
serving.run_simple(HOST, PORT, self._app)
def get_url(self):
return "http://%s:%s" % (HOST, PORT)
def print_serving_message(self):
pass # Werkzeug's `serving.run_simple` handles this
def main():
program = tb.program.TensorBoard(server_class=CustomServer)
program.configure(logdir=os.path.expanduser("~/tensorboard_data"))
program.main()
if __name__ == "__main__":
main()
You can use multiprocessing here: create one process for flask and another for tensorboard, then run it on the same host.
Code:
from multiprocessing import Process
from tensorboard.program import TensorBoard
from flask import Flask, jsonify
app = Flask(__name__)
def tensorboard_main(host, port, logdir):
configuration = list([""])
configuration.extend(["--host", host])
configuration.extend(["--port", port])
configuration.extend(["--logdir", logdir])
tensorboard = TensorBoard()
tensorboard.configure(configuration)
tensorboard.main()
def flask_main(app, host, port):
return app.run(host=host, port=port)
#app.route("/hello-world", methods=["GET", "POST"])
def say_hello():
return jsonify({"result": "Hello world"})
if __name__ == "__main__":
host = "0.0.0.0"
port_for_tensorboard = "7070"
port_for_flask = "5000"
logdir = "/tmp/logdir"
process_for_tensorboard = Process(target=tensorboard_main, args=(host, port_for_tensorboard, logdir))
process_for_flask = Process(target=flask_main, args=(app, host, port_for_flask))
process_for_tensorboard.start()
process_for_flask.start()
process_for_tensorboard.join()
process_for_flask.join()
If you want that inside flask endpoint tensorboard will be show some things, then you need to look at shared data from one process to another (think it would be more complicated than this example)

How to connect/listen to nsqd from a webserver

So I have a simple flask server and wanted to listen to nsqd,(My nsqd and nsqlookupd dockers are running fine.) I'm using gnsq from python as a tool to achieve that
server.py:
from flask import Flask
import gnsq
consumer = gnsq.Consumer('test_topic', 'test_channel', '0.0.0.0:4161')
#consumer.on_message.connect
def handler(consumer, message):
print ('got message:', message.body)
consumer.start()
app = Flask(__name__)
#app.route("/")
def hello():
return "Flasky"
and when I run the server all I get is
[0.0.0.0:4161] connection failed (NSQSocketError(57, 'Socket is not connected'))
I tried changing ports as well but still persist.

global name 'WebServer' is not defined

Please find below code as it is throwing the error - global name 'webserver' is not defined.
import SimpleHTTPServer
import SocketServer
import os
from threading import Thread
import threading
class WebServer(Thread):
def __init__(self, stream_path):
"""
Class to create a Web server and add given folder to the web server which is passed as an argument.
In this case it creates the web server to the incoming streams pushed by VLC to temp folder
"""
Thread.__init__(self)
self.stream_path = stream_path
def run(self):
global WebServer
"""
This method is built in Thread object method invoked by start()
and the code which is under run() will be executed.
"""
os.chdir(self.stream_path)
PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "serving at port", PORT
print "function thread", threading.currentThread()
httpd.serve_forever()
print "test1"
def create_web_server(self,stream_path):
global WebServer
"""
This method is to create the web server to a given path
"""
obj1 = WebServer(self,stream_path)
obj1.start()
print "server created"
def stop_web_server(self):
cmd='tskill python /A'
os.system(cmd)
if __name__ == '__main__':
create_web_server("","C:\\\\QED")
You don't need the two global WebServer lines in your code. The global keyword is used to grant write access to a global variable, and you don't have a global variable named WebServer.
Your code should look like the following to resolve your error, though in its state, it will still throw errors because your code has multiple problems, including calling the create_web_server method by itself, as it's a method that needs to be run on a WebServer object.
I've included a working prototype example of your code at the bottom of my post.
import SimpleHTTPServer
import SocketServer
import os
from threading import Thread
import threading
class WebServer(Thread):
def __init__(self, stream_path):
"""
Class to create a Web server and add given folder to the web server which is passed as an argument.
In this case it creates the web server to the incoming streams pushed by VLC to temp folder
"""
Thread.__init__(self)
self.stream_path = stream_path
def run(self):
"""
This method is built in Thread object method invoked by start()
and the code which is under run() will be executed.
"""
os.chdir(self.stream_path)
PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "serving at port", PORT
print "function thread", threading.currentThread()
httpd.serve_forever()
print "test1"
def create_web_server(self,stream_path):
"""
This method is to create the web server to a given path
"""
obj1 = WebServer(self,stream_path)
obj1.start()
print "server created"
def stop_web_server(self):
cmd='tskill python /A'
os.system(cmd)
if __name__ == '__main__':
create_web_server("","C:\\\\QED")
Here is a simplified version of your code that should do the same thing (serve a directory with a basic SimpleHTTPRequestHandler).
It runs the thread in daemon mode so that it can be interrupted with Ctrl-C. I removed several methods as they didn't seem to serve a purpose in your original code, and to show you a basic framework of what your WebServer class would probably look like.
import threading
import os
import time
import SimpleHTTPServer
import SocketServer
class WebServer(threading.Thread):
# Let's specify additional constructor arguments for host/port
# so you don't have to hardcode those values.
# We can specify default values for them as well.
def __init__(self, stream_path, host='localhost', port=8000):
super(WebServer, self).__init__()
self.stream_path = stream_path
self.host = host
self.port = port
# This is the method that will be called when you call
# .start() on a WebServer object.
def run(self):
os.chdir(self.stream_path)
handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer((self.host, self.port), handler)
httpd.serve_forever()
if __name__ == '__main__':
# Create a WebServer thread object, set it to daemonize
# and start it
ws = WebServer(r'C:\QED')
ws.daemon = True
ws.start()
# Since the main thread doesn't do anything after daemonizing
# the WebServer, it would exit immediately.
# This forever loop just ensures that the main thread runs
while True: time.sleep(1)
And to take it a step further, you don't need to create a Thread subclass. It's allowed because it feels more 'natural' to developers who are familiar with Java, where subclassing Thread or implementing Runnable is standard practice.
You can just do something like:
import threading
import os
import time
import SimpleHTTPServer
import SocketServer
def run_http_server(serve_dir, host='localhost', port=8000):
os.chdir(serve_dir)
handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer((host, port), handler)
httpd.serve_forever()
if __name__ == '__main__':
thread = threading.Thread(target=run_http_server, args=(r'C:\QED',))
thread.daemon = True
thread.start()
while True: time.sleep(1)

Bottle web framework - How to stop?

When starting a bottle webserver without a thread or a subprocess, there's no problem. To exit the bottle app -> CTRL + c.
In a thread, how can I programmatically stop the bottle web server ?
I didn't find a stop() method or something like that in the documentation. Is there a reason ?
For the default (WSGIRef) server, this is what I do (actually it is a cleaner approach of Vikram Pudi's suggestion):
from bottle import Bottle, ServerAdapter
class MyWSGIRefServer(ServerAdapter):
server = None
def run(self, handler):
from wsgiref.simple_server import make_server, WSGIRequestHandler
if self.quiet:
class QuietHandler(WSGIRequestHandler):
def log_request(*args, **kw): pass
self.options['handler_class'] = QuietHandler
self.server = make_server(self.host, self.port, handler, **self.options)
self.server.serve_forever()
def stop(self):
# self.server.server_close() <--- alternative but causes bad fd exception
self.server.shutdown()
app = Bottle()
#app.route('/')
def index():
return 'Hello world'
#app.route('/stop') # not working from here, it has to come from another thread
def stopit():
server.stop()
server = MyWSGIRefServer(port=80)
try:
app.run(server=server)
except:
print('Bye')
When I want to stop the bottle application, from another thread, I do the following:
server.stop()
I had trouble closing a bottle server from within a request as bottle seems to run requests in subprocesses.
I eventually found the solution was to do:
sys.stderr.close()
inside the request (that got passed up to the bottle server and axed it).
An updated version of mike's answer.
from bottlepy.bottle import WSGIRefServer, run
from threading import Thread
import time
class MyServer(WSGIRefServer):
def run(self, app): # pragma: no cover
from wsgiref.simple_server import WSGIRequestHandler, WSGIServer
from wsgiref.simple_server import make_server
import socket
class FixedHandler(WSGIRequestHandler):
def address_string(self): # Prevent reverse DNS lookups please.
return self.client_address[0]
def log_request(*args, **kw):
if not self.quiet:
return WSGIRequestHandler.log_request(*args, **kw)
handler_cls = self.options.get('handler_class', FixedHandler)
server_cls = self.options.get('server_class', WSGIServer)
if ':' in self.host: # Fix wsgiref for IPv6 addresses.
if getattr(server_cls, 'address_family') == socket.AF_INET:
class server_cls(server_cls):
address_family = socket.AF_INET6
srv = make_server(self.host, self.port, app, server_cls, handler_cls)
self.srv = srv ### THIS IS THE ONLY CHANGE TO THE ORIGINAL CLASS METHOD!
srv.serve_forever()
def shutdown(self): ### ADD SHUTDOWN METHOD.
self.srv.shutdown()
# self.server.server_close()
def begin():
run(server=server)
server = MyServer(host="localhost", port=8088)
Thread(target=begin).start()
time.sleep(2) # Shut down server after 2 seconds
server.shutdown()
The class WSGIRefServer is entirely copied with only 1 line added to the run() method is added. Also add a simple shutdown() method. Unfortunately, this is necessary because of the way bottle creates the run() method.
You can make your thread a daemon by setting the daemon property to True before calling start.
mythread = threading.Thread()
mythread.daemon = True
mythread.start()
A deamon thread will stop whenever the main thread that it is running in is killed or dies. The only problem is that you won't be able to make the thread run any code on exit and if the thread is in the process of doing something, it will be stopped immediately without being able to finish the method it is running.
There's no way in Python to actually explicitly stop a thread. If you want to have more control over being able to stop your server you should look into Python Processes from the multiprocesses module.
Since bottle doesn't provide a mechanism, it requires a hack. This is perhaps the cleanest one if you are using the default WSGI server:
In bottle's code the WSGI server is started with:
srv.serve_forever()
If you have started bottle in its own thread, you can stop it using:
srv.shutdown()
To access the srv variable in your code, you need to edit the bottle source code and make it global. After changing the bottle code, it would look like:
srv = None #make srv global
class WSGIRefServer(ServerAdapter):
def run(self, handler): # pragma: no cover
global srv #make srv global
...
Here's one option: provide custom server (same as default), that records itself:
import bottle
class WSGI(bottle.WSGIRefServer):
instances = []
def run(self, *args, **kw):
self.instances.append(self)
super(WSGI, self).run(*args, **kw)
# some other thread:
bottle.run(host=ip_address, port=12345, server=WSGI)
# control thread:
logging.warn("servers are %s", WSGI.instances)
This is exactly the same method than sepero's and mike's answer, but now much simpler with Bottle version 0.13+:
from bottle import W, run, route
from threading import Thread
import time
#route('/')
def index():
return 'Hello world'
def shutdown():
time.sleep(5)
server.srv.shutdown()
server = WSGIRefServer(port=80)
Thread(target=shutdown).start()
run(server=server)
Also related: https://github.com/bottlepy/bottle/issues/1229 and https://github.com/bottlepy/bottle/issues/1230.
Another example with a route http://localhost/stop to do the shutdown:
from bottle import WSGIRefServer, run, route
from threading import Thread
#route('/')
def index():
return 'Hello world'
#route('/stop')
def stopit():
Thread(target=shutdown).start()
def shutdown():
server.srv.shutdown()
server = WSGIRefServer(port=80)
run(server=server)
PS: it requires at least Bottle 0.13dev.
Console log of Bottle server tells us that the official way of shutting down the server is "Hit Ctrl-C":
Bottle v0.12.19 server starting up (using WSGIRefServer())...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.
Why not simply follow it programmatically?
Hitting "Ctrl-C" is nothing but sending SIGINT to the process, and we can achieve it with just built-in modules:
Get current PID with os.getpid().
Kill the process with os.kill(). Remember passing SIGINT so it will be exactly same as "Hit Ctrl-C".
Wrap the 'kill' in another thread and start it after a few seconds so the client won't get error.
Here is the server code:
from bottle import route, run
import os
import signal
from threading import Thread
import time
#route('/hello')
def return_hello():
return 'Hello'
#route('/stop')
def handle_stop_request():
# Handle "stop server" request from client: start a new thread to stop the server
Thread(target=shutdown_server).start()
return ''
def shutdown_server():
time.sleep(2)
pid = os.getpid() # Get process ID of the current Python script
os.kill(pid, signal.SIGINT)
# Kill the current script process with SIGINT, which does same as "Ctrl-C"
run(host='localhost', port=8080)
Here is the client code:
import requests
def request_service(service_key):
url = f'http://127.0.0.1:8080/{service_key}'
response = requests.get(url)
content = response.content.decode('utf-8')
print(content)
request_service('hello')
request_service('stop')
Note that in function "handle_stop_request" we didn't stop the server immediately but rather started a thread then returned empty string. With this mechanism, when a client requests "http://127.0.0.1:8080/stop", it can get response (the empty string) normally. After that, the server will shutdown. If we otherwise shutdown the server in function "handle_stop_request", the server will close the connection before returning to the client, and hence the client will get "ConnectionError".
Server side output:
Bottle v0.12.19 server starting up (using WSGIRefServer())...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.
127.0.0.1 - - [23/Nov/2021 11:18:08] "GET /hello HTTP/1.1" 200 5
127.0.0.1 - - [23/Nov/2021 11:18:08] "GET /stop HTTP/1.1" 200 0
Client side output:
Hello
The code was tested under Python 3.7 and Bottle 0.12.
I suppose that the bottle webserver runs forever until it terminates. There are no methonds like stop().
But you can make something like this:
from bottle import route, run
import threading, time, os, signal, sys, operator
class MyThread(threading.Thread):
def __init__(self, target, *args):
threading.Thread.__init__(self, target=target, args=args)
self.start()
class Watcher:
def __init__(self):
self.child = os.fork()
if self.child == 0:
return
else:
self.watch()
def watch(self):
try:
os.wait()
except KeyboardInterrupt:
print 'KeyBoardInterrupt'
self.kill()
sys.exit()
def kill(self):
try:
os.kill(self.child, signal.SIGKILL)
except OSError: pass
def background_process():
while 1:
print('background thread running')
time.sleep(1)
#route('/hello/:name')
def index(name='World'):
return '<b>Hello %s!</b>' % name
def main():
Watcher()
MyThread(background_process)
run(host='localhost', port=8080)
if __name__ == "__main__":
main()
Then you can use Watcher.kill() when you need to kill your server.
Here is the code of run() function of the bottle:
try:
app = app or default_app()
if isinstance(app, basestring):
app = load_app(app)
if not callable(app):
raise ValueError("Application is not callable: %r" % app)
for plugin in plugins or []:
app.install(plugin)
if server in server_names:
server = server_names.get(server)
if isinstance(server, basestring):
server = load(server)
if isinstance(server, type):
server = server(host=host, port=port, **kargs)
if not isinstance(server, ServerAdapter):
raise ValueError("Unknown or unsupported server: %r" % server)
server.quiet = server.quiet or quiet
if not server.quiet:
stderr("Bottle server starting up (using %s)...\n" % repr(server))
stderr("Listening on http://%s:%d/\n" % (server.host, server.port))
stderr("Hit Ctrl-C to quit.\n\n")
if reloader:
lockfile = os.environ.get('BOTTLE_LOCKFILE')
bgcheck = FileCheckerThread(lockfile, interval)
with bgcheck:
server.run(app)
if bgcheck.status == 'reload':
sys.exit(3)
else:
server.run(app)
except KeyboardInterrupt:
pass
except (SyntaxError, ImportError):
if not reloader: raise
if not getattr(server, 'quiet', False): print_exc()
sys.exit(3)
finally:
if not getattr(server, 'quiet', False): stderr('Shutdown...\n')
As you can see there are no other way to get off the run loop, except some exceptions.
The server.run function depends on the server you use, but there are no universal quit-method anyway.
This equally kludgy hack has the advantage that is doesn't have you copy-paste any code from bottle.py:
# The global server instance.
server = None
def setup_monkey_patch_for_server_shutdown():
"""Setup globals to steal access to the server reference.
This is required to initiate shutdown, unfortunately.
(Bottle could easily remedy that.)"""
# Save the original function.
from wsgiref.simple_server import make_server
# Create a decorator that will save the server upon start.
def stealing_make_server(*args, **kw):
global server
server = make_server(*args, **kw)
return server
# Patch up wsgiref itself with the decorated function.
import wsgiref.simple_server
wsgiref.simple_server.make_server = stealing_make_server
setup_monkey_patch_for_server_shutdown()
def shutdown():
"""Request for the server to shutdown."""
server.shutdown()
I've found this solution to be the easiest, but it does require that the "psutil" package is installed, to get the current process. It also requires the "signals" module, but that's part of the standard library.
#route('/shutdown')
def shutdown():
current_process = psutil.Process()
current_process.send_signal(signal.CTRL_C_EVENT)
return 'Shutting down the web server'
Hope that's of use to someone!
This question was top in my google search, so i will post my answer:
When the server is started with the Bottle() class, it has a method close() to stop the server. From the source code:
""" Close the application and all installed plugins. """
For example:
class Server:
def __init__(self, host, port):
self._host = host
self._port = port
self._app = Bottle()
def stop(self):
# close ws server
self._app.close()
def foo(self):
# More methods, routes...
Calling stop method will stop de server.

Categories