使用Flask服务器的面向对象Python?

使用Flask服务器的面向对象Python?,python,flask,Python,Flask,我使用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 ra

我使用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()
时,它工作正常。但是,当我使用Flask运行此操作时,会出现
500内部服务器错误
。这里没有魔法,Flask也不知道它应该初始化一个
MyServer
对象。如何将MyServer实例馈送到
app.run()
命令


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

您可以在端点范围之外创建
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")

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

这是非常可测试的——只需在测试代码中使用模拟/伪造的依赖项(
database\u interface
filesystem\u interface
)调用
init\u app()您已经准备好编写覆盖整个应用程序(包括烧瓶路由)的测试


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

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

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)

如果您希望将MyServer类作为一种资源进行访问
我相信这可以帮助你:

from flask import Flask
from flask_restful import Resource, Api
import json
import numpy as np

app = Flask(__name__)
api = Api(app)

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

    def get(self):
        return np.random.choice(self.globalData)

api.add_resource(MyServer, '/')

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

我知道这是一个迟来的答复,但我在面对类似问题时遇到了这个问题。我发现这瓶酒真的很好。 您从FlaskView继承类,并向MyServer类注册Flask应用程序

在本例中,使用flask classful,您的代码如下所示:

从烧瓶导入烧瓶
从flask_classful导入FlaskView,路线
app=烧瓶(名称)
类MyServer(FlaskView):
定义初始化(自):
globalData=json.load(文件名)
@路由(“/getSomeData”)
def getSomeData():
return random.choice(globalData)#选择一些要返回的随机数据
MyServer.register(应用程序,base_route=“/”)
如果名称=“\uuuuu main\uuuuuuuu”:
app.run(host='0.0.0.0')

这是一个不错的选择,但您仍然无法编写端到端测试和模拟依赖项(如网络或文件系统IO),因为您的依赖项没有被注入。你可以做一些像
unittest.mock.patch
这样的黑客行为,但是你必须像构建测试服务器一样小心构建真正的服务器(当然除了mock之外)。这基本上是服务器中传递的单例反模式flask。获取MyServer实例的\u数据,但请求数据在哪里?请将
flask classful
替换为
flask\u classful
(请参阅)
from flask import Flask
from flask_restful import Resource, Api
import json
import numpy as np

app = Flask(__name__)
api = Api(app)

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

    def get(self):
        return np.random.choice(self.globalData)

api.add_resource(MyServer, '/')

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