按需启动和停止烧瓶 [英] Starting and stopping flask on demand

查看:87
本文介绍了按需启动和停止烧瓶的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个应用程序,它可以公开使用flask实现的简单RPC接口.但是,我希望可以激活和停用该界面.同样,应该有可能在同一个python解释器中运行应用程序的多个实例,每个实例都有各自的RPC接口.

该服务仅公开给localhost,这是一个原型,因此我不担心安全性.我正在寻找一个小而简单的解决方案.这里最明显的方法似乎是使用flask开发服务器,但是我找不到关闭它的方法.

我已经为要公开的功能创建了一个烧瓶蓝图,现在我正试图编写一个类来包装类似于以下内容的RPC接口:

 类RPCInterface:def __init __(自己,creating_app,配置):self.flask_app =烧瓶(__name__)self.flask_app.config.update(config)self.flask_app.my_app = creation_appself.flask_app.register_blueprint(my_blueprint)self.flask_thread =线程(target = Flask.run,args =(self.flask_app,),name ='flask_thread',daemon = True)def shutdown(个体):#使用Flask服务器似乎不可能引发NotImplemented() 

我正在使用当前应用程序的变量my_app将此RPC接口正在使用的应用程序实例传递到请求的上下文中.

可以从请求内部将其关闭(如此处所述 http://flask.pocoo.org/snippets/67/),因此一种解决方案是创建关闭端点,并与测试客户端发送请求以启动关闭请求.但是,这仅需要烧瓶端点即可.这远非干净.

我研究了flask和werkzeug的源代码,并找出了重要的部分(上下文位于 https://github.com/pallets/werkzeug/blob/master/werkzeug/serving.py#L688 )如下所示:

  def inner():尝试:fd = int(os.environ ['WERKZEUG_SERVER_FD'])除了(LookupError,ValueError):fd =无srv = make_server(主机名,端口,应用程序,线程,流程,request_handler,passthrough_errors,ssl_context,fd = fd)如果fd为None:log_startup(srv.socket)srv.serve_forever() 

make_server 返回werkzeugs服务器类的实例,该类继承自pythons http.server 类.这又是一个Python BaseSocketServer ,它公开了一个shutdown方法.问题在于,此处创建的服务器只是一个局部变量,因此无法从任何地方访问.

这是我陷入死胡同的地方.所以我的问题是:

  • 有人有另一个想法如何轻松关闭此服务器吗?
  • 是否还有其他简单的服务器可以在烧瓶上运行?不需要外部过程就能在几行代码中启动和停止的事情?flask文档中列出的所有内容似乎都具有复杂的设置.

解决方案

回答我自己的问题,以防万一.

第一个解决方案涉及从烧瓶切换到 klein .Klein基本上是烧瓶,功能较少,但运行在扭曲反应器的顶部.这样,集成非常简单.基本上它是这样的:

 从klein导入Klein来自twist.internet进口反应堆应用= Klein()@ app.route('/')def home(要求):返回某些网站"端点= serverFromString(反应堆,端点字符串)endpoint.listen(Site(app.resource()))react.run() 

现在,所有扭曲的工具都可以根据需要用于启动和停止服务器.

我切换到更深层次的第二个解决方案是摆脱HTTP作为传输协议.我在扭曲的LineReceiver协议之上切换到JSONRPC.这样,一切都变得更加简单,而且我还是不使用任何HTTP东西.

I am writing an application, which can expose a simple RPC interface implemented with flask. However I want it to be possible to activate and deactivate that interface. Also it should be possible to have multiple instances of the application running in the same python interpreter, which each have their own RPC interface.

The service is only exposed to localhost and this is a prototype, so I am not worried about security. I am looking for a small and easy solution. The obvious way here seems to use the flask development server, however I can't find a way to shut it down.

I have created a flask blueprint for the functionality I want to expose and now I am trying to write a class to wrap the RPC interface similar to this:

class RPCInterface:
    def __init__(self, creating_app, config):
        self.flask_app = Flask(__name__)
        self.flask_app.config.update(config)
        self.flask_app.my_app = creating_app

        self.flask_app.register_blueprint(my_blueprint)

        self.flask_thread = Thread(target=Flask.run, args=(self.flask_app,),
                                   name='flask_thread', daemon=True)

    def shutdown(self):
        # Seems impossible with the flask server
        raise NotImplemented()

I am using the variable my_app of the current app to pass the instance of my application this RPC interface is working with into the context of the requests.

It can be shut down from inside a request (as described here http://flask.pocoo.org/snippets/67/), so one solution would be to create a shutdown endpoint and send a request with the test client to initiate a shutdown. However that requires a flask endpoint just for this purpose. This is far from clean.

I looked into the source code of flask and werkzeug and figured out the important part (Context at https://github.com/pallets/werkzeug/blob/master/werkzeug/serving.py#L688) looks like this:

def inner():
    try:
        fd = int(os.environ['WERKZEUG_SERVER_FD'])
    except (LookupError, ValueError):
        fd = None
    srv = make_server(hostname, port, application, threaded,
                      processes, request_handler,
                      passthrough_errors, ssl_context,
                      fd=fd)
    if fd is None:
        log_startup(srv.socket)
    srv.serve_forever()

make_server returns an instance of werkzeugs server class, which inherits from pythons http.server class. This in turn is a python BaseSocketServer, which exposes a shutdown method. The problem is that the server created here is just a local variable and thus not accessible from anywhere.

This is where I ran into a dead end. So my question is:

  • Does anybody have another idea how to shut down this server easily?
  • Is there any other simple server to run flask on? Something which does not require an external process and can just be started and stopped in a few lines of code? Everything listed in the flask doc seems to have a complex setup.

解决方案

Answering my own question in case this ever happens again to anyone.

The first solution involved switching from flask to klein. Klein is basically flask with less features, but running on top of the twisted reactor. This way the integration is very simple. Basically it works like this:

from klein import Klein
from twisted.internet import reactor

app = Klein()

@app.route('/')
def home(request):
    return 'Some website'

endpoint = serverFromString(reactor, endpoint_string)
endpoint.listen(Site(app.resource()))

reactor.run()

Now all the twisted tools can be used to start and stop the server as needed.

The second solution I switched to further down the road was to get rid of HTTP as a transport protocol. I switched to JSONRPC on top of twisted's LineReceiver protocol. This way everything got even simpler and I didn't use any of the HTTP stuff anyway.

这篇关于按需启动和停止烧瓶的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆