集成Flask/Dill来转储/加载服务器会话



我正在尝试将Flask与Dill集成在服务器端转储/加载Python会话。下面的代码有两个函数,第一个函数将x的值设置为零并导入datetime库。第二个将x加1并获得时间戳。

第一个函数转储会话,第二个函数加载会话。

在转储中,pickle文件是正确生成的,但是我不能重用x或获取时间戳。

这是当我尝试在第二个函数中执行x = x + 1时的错误:

UnboundLocalError: local variable 'x' referenced before assignment

Dill可以与Flask一起使用吗?我需要一个不同的方法吗?

代码:

from flask import Flask
from dill import dump_session, load_session
app = Flask(__name__)
app.config['SECRET_KEY'] = 'super secret'
session_file = '/tmp/session.pkl'
@app.route('/start_counter')
def start_counter():
import datetime
x = 0
dump_session(filename = session_file)
return 'New counter started!'
@app.route('/count')
def count():
load_session(filename = session_file)
x = x + 1
now = datetime.datetime.now()
dump_session(filename = session_file)
return str(x) + '-' + str(now)

如何修复?

为了简单起见,您需要一个数据结构来保存应用程序状态。我会使用dict,因为它很简单,但你也可以为它定义一个类。

最简单(也是最繁琐)的方法是每次需要应用程序状态时调用state = dill.load('filename')dill.dump(object,'filename')

如果您的应用程序很小,那么将起作用。如果您需要维护一个适当的应用程序状态,您应该使用数据库。

Ok。但这里发生了什么?

dill和Flask没有兼容性问题。

调用dill.dump_session()时,保存__main__的状态。

但是,当你在函数count()中增加x时,它是未定义的,因为它没有被dill保存。

一个简单的方法是将breakpoint()放在x = x + 1之前,或者将内容打印在try..except子句中:

try:
print(x)
except ee:
print(ee)
pass;
x = x + 1

所以,它没有工作,因为变量x没有在__main__中定义,而是在start_counter()函数的范围内,dill.load_session()恢复了__main__中的东西。

__main__是什么意思?

让我们看看使用Repl:

~/$ python
Python 3.8.10 (tags/v3.8.10:3d8993a, May  3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

完美。我们有一个空的python解释器。dir()显示了我们在__main__中的内容。

现在我们将加载一些库,赋值一个变量,定义一个函数,因为我们可以:

>>> import pandas, numpy, dill, pickle, json, datetime
>>> foo = "bar"
>>> def functionWithUglyName():
...    print("yep")
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'datetime', 'dill', 'foo', 'functionWithUglyName', 'json', 'numpy', 'pandas', 'pickle']```

__main__的东西看起来更密集。

现在我们保存会话并退出Repl:

>>> dill.dump_session('session_01')
>>>  exit()

当我们用' dill.load_session()'加载会话时会发生什么?

让我们打开另一个Repl来发现它:

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

Ok。只是另一个空的python解释器…

让我们加载会话,看看会发生什么:

>>> import dill
>>> dill.load_session('session_01')
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'datetime', 'dill', 'foo', 'functionWithUglyName', 'json', 'numpy', 'pandas', 'pickle']

按预期加载__main__的内容。等一下。它加载了我们之前定义的functionWithUglyName。这是真的吗?

>>> functionWithUglyName()
yep

原来迪尔真的很擅长连载东西。大多数情况下,您只需要pickle一些数据,但莳萝可以做更多……它非常适合调试和测试。

相关内容

  • 没有找到相关文章

最新更新