带Flask服务器的面向对象Python?

2024-04-20 08:52:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用Flask将一些数据处理代码作为web服务公开。 我想要一些我的Flask函数可以访问的类变量。

让我带你穿过我被困的地方:

from flask import Flask
app = Flask(__name__)

class MyServer:
  def __init__(self):
    globalData = json.load(filename)

  @app.route('/getSomeData')
  def getSomeData():
    return random.choice(globalData) #select some random data to return

if __name__ == "__main__":
  app.run(host='0.0.0.0')

当我在烧瓶外运行getSomeData()时,它工作正常。但是,当我用烧瓶运行时,我得到500 internal server error。这里没有魔法,Flask也不知道它应该初始化一个MyServer对象。如何将MyServer实例馈送给app.run()命令?

我可以承认失败,把globalData放入数据库。但是,还有别的办法吗?


Tags: 函数run代码namewebappflaskreturn
4条回答

您可以在端点范围之外创建MyServer的实例并访问其属性。这对我有效:

class MyServer:
    def __init__(self):
        self.globalData = "hello"

from flask import Flask
app = Flask(__name__)

my_server = MyServer()

@app.route("/getSomeData")
def getSomeData():
    return my_server.globalData

if __name__ == "__main__":
    app.run(host="0.0.0.0")

有点晚了,但这里有一个快速的实现,我用它在初始化时注册路由

from flask import Flask,request,render_template
from functools import partial


registered_routes = {}
def register_route(route=None):
    #simple decorator for class based views
    def inner(fn):
        registered_routes[route] = fn
        return fn
    return inner

class MyServer(Flask):
    def __init__(self,*args,**kwargs):
        if not args:
            kwargs.setdefault('import_name',__name__)
        Flask.__init__(self,*args ,**kwargs)
        # register the routes from the decorator
        for route,fn in registered_routes.items():
            partial_fn = partial(fn,self)
            partial_fn.__name__ = fn.__name__
            self.route(route)(partial_fn)


    @register_route("/")
    def index(self):
        return render_template("my_template.html")

if __name__ == "__main__":
    MyServer(template_folder=os.path.dirname(__file__)).run(debug=True)

最不耦合的解决方案是在运行时(而不是在加载时)应用路由:

def init_app(flask_app, database_interface, filesystem_interface):
    server = MyServer(database_interface, filesystem_interface)
    flask_app.route('get_data', methods=['GET'])(server.get_data)

这是非常可测试的——只要用模拟/伪造的依赖项(database_interfacefilesystem_interface)调用测试代码中的init_app()和一个已经配置用于测试的flask应用程序(app.config["TESTING"]=True或类似的东西),就可以编写覆盖整个应用程序(包括flask路由)的测试。

唯一的缺点是这不是很“Flasky”(或者我听说过);Flasky的习惯用法是使用@app.route(),这是在加载时应用的,并且必然是紧密耦合的,因为依赖项是硬编码到实现中的,而不是注入到某个构造函数或工厂方法中(因此测试起来很复杂)。

最不耦合的解决方案是在运行时(而不是在加载时)应用路由:

def init_app(flask_app, database_interface, filesystem_interface):
    server = MyServer(database_interface, filesystem_interface)
    flask_app.route('get_data', methods=['GET'])(server.get_data)

这是非常可测试的——只需在测试代码中使用模拟/伪造的依赖项(database_interfacefilesystem_interface)调用init_app(),以及配置用于测试的flask应用程序(app.config["TESTING"]=True或类似的东西),就可以编写覆盖整个应用程序(包括flask路由)的测试。

唯一的缺点是这不是很“Flasky”(或者我听说过);Flasky的习惯用法是使用@app.route(),这是在加载时应用的,并且必然是紧密耦合的,因为依赖项是硬编码到实现中的,而不是注入到某个构造函数或工厂方法中(因此测试起来很复杂)。

相关问题 更多 >