在没有线程或子进程的情况下启动瓶子网络服务器时,没有问题.要退出瓶子应用程序 - > CTRL+ c.
在一个帖子中,我如何以编程方式停止瓶网服务器?
我没有stop()在文档中找到方法或类似的东西.有原因吗?
mik*_*ike 12
对于默认(WSGIRef)服务器,这就是我所做的(实际上它是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
Run Code Online (Sandbox Code Playgroud)
当我想从另一个线程停止瓶子应用程序时,我会执行以下操作:
server.stop()
Run Code Online (Sandbox Code Playgroud)
小智 8
我无法在请求中关闭瓶子服务器,因为瓶子似乎在子流程中运行请求.
我最终发现解决方案是:
sys.stderr.close()
Run Code Online (Sandbox Code Playgroud)
请求内部(已经传递给瓶子服务器并将其砍掉).
迈克答案的更新版本.
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()
Run Code Online (Sandbox Code Playgroud)
WSGIRefServer类是完全复制的,只添加了一行添加到run()方法中.还添加一个简单的shutdown()方法.不幸的是,由于bottle创建run()方法的方式,这是必要的.
我认为 Bottle Web 服务器会永远运行直到终止。没有类似的方法stop()。
但你可以做这样的事情:
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()
Run Code Online (Sandbox Code Playgroud)
Watcher.kill()然后当你需要杀死你的服务器时就可以使用。
run()这是瓶子的功能代码:
尝试:app = app或default_app()如果isinstance(app,basestring):app = load_app(app)如果不可调用(app):引发ValueError(“应用程序不可调用:%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')
Run Code Online (Sandbox Code Playgroud)
run正如您所看到的,除了一些例外之外,没有其他方法可以摆脱循环。该server.run功能取决于您使用的服务器,但无论如何没有通用的quit方法。