我有以下应用程序,它运行调度程序定期更新全局变量(dict)的状态:
from sanic import Sanic
from sanic.response import text
from apscheduler.schedulers.background import BackgroundScheduler
import bumper
app = Sanic()
scheduler = BackgroundScheduler()
inventory = {1: 1, 2: 2}
@scheduler.scheduled_job('interval', seconds=5)
def bump():
bumper.bump()
@scheduler.scheduled_job('interval', seconds=10)
def manual_bump():
global inventory
inventory[2] += 1
@app.route("/")
async def test(request):
return text(inventory)
if __name__ == "__main__":
scheduler.start()
app.run(host="0.0.0.0", port=8000)
在5秒间隔作业中导入的函数位于同一目录中的不同文件中:
^{pr2}$但这并不像我希望的那样有效。导入的函数更新库存,但更改从未传播到原始字典,因此bump_inventory
正在处理inventory
的副本,或者从不在函数范围之外更新它。在两个不同的终端中:
]$ python app.py
2017-02-19 14:11:45,643: INFO: Goin' Fast @ http://0.0.0.0:8000
2017-02-19 14:11:45,644: INFO: Starting worker [26053]
new {1: 2, 2: 2}
new {1: 3, 2: 2}
]$ while true; do curl http://0.0.0.0:8000/; echo; sleep 1; done
{1: 1, 2: 2}
...
{1: 1, 2: 3}
...
正确的方法是什么?在
1-不需要将
apscheduler
与asyncio一起使用。您已经在asyncio中内置了所需的所有工具,并且它与Sanic配合得很好。在2-不建议使用全局状态,尤其是在web应用程序场景中。你应该使用数据库或Redis。但如果出于某种原因需要应用程序状态,可以将其存储在
app
对象上。在Sanic的下一个版本将有一个
add_task
方法,用于向应用程序添加异步任务。如果要立即使用,可以从Github安装主分支:明白了。仍然不确定为什么共享变量没有更新(我的猜测仍然是它是一个副本),但是将它作为一个参数传递到函数中可以正常工作(因为我们传递的是对象的引用,而不是实际对象)。将5秒的间隔修改为:
这还会删除另一个文件中的循环导入(即删除
from app import inventory
)。在相关问题 更多 >
编程相关推荐