template tag example python bottle

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 ().