mar*_*t1n 1 python dictionary global apscheduler sanic
我有以下应用程序运行调度程序来定期更新全局变量(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)
Run Code Online (Sandbox Code Playgroud)
在5秒间隔作业中导入的函数位于同一目录中的不同文件中:
from app import inventory
def bump_inventory():
inventory[1] += 1
print('new', inventory)
Run Code Online (Sandbox Code Playgroud)
然而,这并不像我希望的那样有效.导入的函数更新库存,但更改永远不会传播到原始字典,因此要么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}
...
Run Code Online (Sandbox Code Playgroud)
这样做的正确方法是什么?
1-没有必要使用apschedulerasyncio.你拥有所需的所有设施都可以内置到asyncio中,它可以很好地与Sanic配合使用.
2-建议不要使用全局状态,尤其是在Web应用程序方案中.您应该使用数据库或Redis.但是如果由于某种原因需要应用程序状态,则可以将其存储在app对象上.
下一版Sanic将为您提供一种add_task方法,可以将asyncio任务添加到您的应用程序中.如果您想立即使用它,可以从Github安装master分支:
import asyncio
from sanic import Sanic
from sanic.response import text
app = Sanic()
app.inventory = {1:1, 2:2}
async def five_second_job(app):
while True:
app.inventory[1] += 1
await asyncio.sleep(5)
async def ten_second_job(app):
while True:
app.inventory[2] += 2
await asyncio.sleep(10)
@app.route("/")
async def test(request):
return text(app.inventory)
if __name__ == "__main__":
app.add_task(five_second_job(app))
app.add_task(ten_second_job(app))
app.run(host="0.0.0.0", port=9000)
Run Code Online (Sandbox Code Playgroud)