将 Flask/Dill 集成到 dump/load 服务器会话
Integrating Flask/Dill to dump/load server sessions
我正在尝试将 Flask 与 Dill 集成到服务器端的 dump/load 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
因为它很简单,但您也可以为此定义 class。
简单(且乏味)的方法是在每次需要应用程序状态时调用 state = dill.load('filename')
和 dill.dump(object,'filename')
。
如果您的应用程序很小,这将有效。如果您需要维护适当的应用程序状态,您应该使用数据库。
好的。但是这里发生了什么?
dill 和 Flask 没有兼容性问题。
当您调用 dill.dump_session()
时,它会保存 __main__
的状态。
但是,当你在函数 count()
中增加 x
时,它是未定义的,因为它没有被 dill 保存。
一个简单的方法是在 x = x + 1
之前放置一个 breakpoint()
或打印 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__']
好的。只是另一个空 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
原来 dill 真的很擅长序列化东西。
大多数时候你只需要 pickle 一些数据,但 dill 可以做更多......而且它非常适合调试和测试。
我正在尝试将 Flask 与 Dill 集成到服务器端的 dump/load 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
因为它很简单,但您也可以为此定义 class。
简单(且乏味)的方法是在每次需要应用程序状态时调用 state = dill.load('filename')
和 dill.dump(object,'filename')
。
如果您的应用程序很小,这将有效。如果您需要维护适当的应用程序状态,您应该使用数据库。
好的。但是这里发生了什么?
dill 和 Flask 没有兼容性问题。
当您调用 dill.dump_session()
时,它会保存 __main__
的状态。
但是,当你在函数 count()
中增加 x
时,它是未定义的,因为它没有被 dill 保存。
一个简单的方法是在 x = x + 1
之前放置一个 breakpoint()
或打印 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__']
好的。只是另一个空 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
原来 dill 真的很擅长序列化东西。 大多数时候你只需要 pickle 一些数据,但 dill 可以做更多......而且它非常适合调试和测试。