python - example - url tag django
Botella web framework-¿Cómo parar? (9)
Aquí hay una opción: proporcionar un servidor personalizado (igual que el predeterminado), que se registra a sí mismo:
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)
Al iniciar un servidor web de botella sin subproceso o subproceso, no hay problema. Para salir de la aplicación de la botella -> CTRL
+ c
.
En un hilo, ¿cómo puedo detener programáticamente el servidor web de botella?
No encontré un método stop()
o algo así en la documentación. Hay una razón ?
Dado que la botella no proporciona un mecanismo, requiere un corte. Este es quizás el más limpio si está utilizando el servidor WSGI predeterminado:
En el código de la botella, el servidor WSGI se inicia con:
srv.serve_forever()
Si ha comenzado la botella en su propio hilo, puede detenerla usando:
srv.shutdown()
Para acceder a la variable srv en su código, necesita editar el código fuente de la botella y hacerlo global. Después de cambiar el código de la botella, se vería así:
srv = None #make srv global
class WSGIRefServer(ServerAdapter):
def run(self, handler): # pragma: no cover
global srv #make srv global
...
Esta pregunta fue superior en mi búsqueda de Google, así que publicaré mi respuesta:
Cuando el servidor se inicia con la clase Bottle (), tiene un método close () para detener el servidor. Desde el código fuente:
"" "Cierre la aplicación y todos los complementos instalados." ""
Por ejemplo:
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...
El método de parada de llamada detendrá el servidor.
Este truco igualmente kludgy tiene la ventaja de que no tiene que copiar y pegar ningún código de 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()
Para el servidor predeterminado (WSGIRef), esto es lo que hago (en realidad es un enfoque más limpio de la sugerencia de Vikram Pudi):
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()
server = MyWSGIRefServer(host=listen_addr, port=listen_port)
try:
app.run(server=server)
except Exception,ex:
print ex
Cuando quiero detener la aplicación de la botella, desde otro hilo, hago lo siguiente:
server.stop()
Puede hacer que su hilo sea un demonio estableciendo la propiedad del demonio en Verdadero antes de llamar al inicio.
mythread = threading.Thread()
mythread.daemon = True
mythread.start()
Un hilo de deamon se detendrá siempre que el hilo principal en el que se está ejecutando muera o muera. El único problema es que no podrá hacer que el subproceso ejecute ningún código al salir y si el subproceso está en el proceso de hacer algo, se detendrá de inmediato sin poder finalizar el método que se está ejecutando.
No hay manera en Python de detener explícitamente un hilo. Si desea tener más control sobre la posibilidad de detener su servidor, debe consultar los Processes Python desde el módulo de multiprocesses .
Supongo que el servidor web botella funciona para siempre hasta que termina. No hay métodos como stop()
.
Pero puedes hacer algo como esto:
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()
Luego puede usar Watcher.kill()
cuando necesite matar su servidor.
Aquí está el código de la función run()
de la botella:
intente: app = app o default_app () si es instancia (app, basestring): app = load_app (app) si no se puede llamar (app): raise ValueError ("La aplicación no se puede llamar:% 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'')
Como puede ver, no hay otra forma de salir del ciclo de run
, excepto algunas excepciones. La función server.run
depende del servidor que use, pero de todos modos no hay un método de quit
universal.
Tuve problemas para cerrar un servidor de botella desde dentro de una solicitud, ya que la botella parece ejecutar solicitudes en subprocesos.
Finalmente encontré que la solución era hacer:
sys.stderr.close()
dentro de la solicitud (que se pasó al servidor de la botella y se eliminó).
Una versión actualizada de la respuesta de mike.
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()
La clase WSGIRefServer se copia completamente con solo 1 línea agregada al método run () se agrega. También agregue un método simple shutdown (). Desafortunadamente, esto es necesario debido a la forma en que la botella crea el método run ().