Python 在课堂内使用烧瓶

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40460846/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 23:34:23  来源:igfitidea点击:

Using flask inside class

pythonflask

提问by George Shuklin

I have application with many threads. One of them is flask, which is used to implement (axillary) API. It used with low load and never exposed to the Internet, so build-in flask web server is perfectly fine.

我有很多线程的应用程序。其中之一是flask,用于实现(腋)API。它在低负载下使用,从不暴露在互联网上,因此内置的 Flask Web 服务器非常好。

My current code looks like this:

我当前的代码如下所示:

class API:
    # ... all other stuff here, skipped
    def run():
        app = flask.Flask('API')

        @app.route('/cmd1')
        def cmd1():
            self.cmd1()

        @app.route('/cmd2')
        def cmd2()
            self.cmd2()

        app.run()

I feel I done it wrong, because all docs says 'create flask app at module level'. But I don't want to do this - it mess up with my tests, and API is small part of the larger application, which has own structure and agreements (each 'application' is separate class running in one or more threads).

我觉得我做错了,因为所有文档都说“在模块级别创建烧瓶应用程序”。但我不想这样做 - 它会干扰我的测试,而且 API 是更大应用程序的一小部分,它有自己的结构和协议(每个“应用程序”都是在一个或多个线程中运行的独立类)。

How can I use Flask inside class?

如何在课堂上使用 Flask?

回答by Kostas Pelelis

Although this works it doesn't feel compliant with the Flask style guide. If you need to wrap a Flask application inside your project, create a separate class to your needs and add functions that should be executed

虽然这有效,但感觉不符合 Flask 风格指南。如果您需要在项目中包装 Flask 应用程序,请根据需要创建一个单独的类并添加应执行的函数

from flask import Flask, Response


class EndpointAction(object):

    def __init__(self, action):
        self.action = action
        self.response = Response(status=200, headers={})

    def __call__(self, *args):
        self.action()
        return self.response


class FlaskAppWrapper(object):
    app = None

    def __init__(self, name):
        self.app = Flask(name)

    def run(self):
        self.app.run()

    def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None):
        self.app.add_url_rule(endpoint, endpoint_name, EndpointAction(handler))


def action():
    # Execute anything

a = FlaskAppWrapper('wrap')
a.add_endpoint(endpoint='/ad', endpoint_name='ad', handler=action)
a.run()

Some things to note here:

这里需要注意的一些事项:

  • EndpointActionis supposed to be a wrapper that will execute your function and generate an empty 200 response. If you want you can edit the functionality
  • The endpoint handler can be anything that has a __call__method defined
  • The endpoint name should be unique as it represents a view name
  • Adding endpoints after the application is not possible as the thread will block once the application starts. You can enable it by running the application on a separate thread but changing the URL map on the fly is not advised, neither thread safe
  • EndpointAction应该是一个包装器,它将执行您的函数并生成一个空的 200 响应。如果你愿意,你可以编辑功能
  • 端点处理程序可以是任何__call__定义了方法的东西
  • 端点名称应该是唯一的,因为它代表一个视图名称
  • 在应用程序之后添加端点是不可能的,因为一旦应用程序启动线程就会阻塞。您可以通过在单独的线程上运行应用程序来启用它,但不建议动态更改 URL 映射,这也不是线程安全的

回答by ZettaCircl

To complete Kostas Pelelis's answer, because I had some difficulty to find the why the Response wasn't directly using the Action returned value.

完成 Kostas Pelelis 的回答,因为我很难找到 Response 不直接使用 Action 返回值的原因。

Here is another version of FLASK class without decorators :

这是没有装饰器的另一个版本的 FLASK 类:

class EndpointAction(object):

def __init__(self, action):
    self.action = action

def __call__(self, *args):
    # Perform the action
    answer = self.action()
    # Create the answer (bundle it in a correctly formatted HTTP answer)
    self.response = flask.Response(answer, status=200, headers={})
    # Send it
    return self.response

class FlaskAppWrapper(object):

def add_all_endpoints(self):
    # Add root endpoint
    self.add_endpoint(endpoint="/", endpoint_name="/", handler=self.action)

    # Add action endpoints
    self.add_endpoint(endpoint="/add_X", endpoint_name="/add_X", handler=self.add_X)
    # you can add more ... 

def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None):
    self.app.add_url_rule(endpoint, endpoint_name, EndpointAction(handler)) 
    # You can also add options here : "... , methods=['POST'], ... "

# ==================== ------ API Calls ------- ====================
def action(self):
    # Dummy action
    return "action" # String that will be returned and display on the webpage
    # Test it with curl 127.0.0.1:5000

def add_X(self):
    # Dummy action
    return "add_X"
    # Test it with curl 127.0.0.1:5000/add_X

回答by Hymanson Jegatheesan

so I just came across the library Flask-Classful

所以我刚遇到图书馆Flask-Classful

which was really simple comparatively
To create a simple web app inside a class is this

相对来说这真的很简单
在一个类中创建一个简单的网络应用程序是这样的

from flask import Flask
from flask_classful import FlaskView

app = Flask(__name__)

class TestView(FlaskView):

    def index(self):
    # http://localhost:5000/
        return "<h1>This is my indexpage</h1>"

TestView.register(app,route_base = '/')

if __name__ == '__main__':
    app.run(debug=True) 

Handling multiple route and dynamic route is also simple

处理多路由和动态路由也很简单

class TestView(FlaskView):

    def index(self):
    # http://localhost:5000/
        return "<h1>This is my indexpage</h1>"

    def secondpage(self):
    # http://localhost:5000/secondpage
        return "<h1>This is my second</h1>"

    def thirdpage(self,name):
    # dynamic route
    # http://localhost:5000/thirdpage/sometext
        return "<h1>This is my third page <br> welcome"+name+"</h1>"

TestView.register(app,route_base = '/')

Adding own route name with a different method that is also possible

使用不同的方法添加自己的路线名称也是可能的

from flask_classful import FlaskView,route

class TestView(FlaskView):

    def index(self):
    # http://localhost:5000/
        return "<h1>This is my indexpage</h1>"


    @route('/diffrentname')
    def bsicname(self):
    # customized route
    # http://localhost:5000/diffrentname
        return "<h1>This is my coustom route</h1>"
TestView.register(app,route_base = '/')

This gives the potential to create separate class and handlers for a separate dependent and independent process and just import them as a package to run on main file or wrapper file

这提供了为单独的依赖和独立进程创建单独的类和处理程序的可能性,并将它们作为包导入以在主文件或包装文件上运行

from package import Classname
Classname.register(app,route_base = '/')

which is really simple and object overiented

这非常简单且面向对象