我有一些将在服务器中运行的代码。运行可能需要很长时间(至少几分钟)。我希望能够轮询服务器以了解当前代码在哪里。我以为可以使用asyncio
来做到这一点,但看起来可能不是我所需要的。
这是我编写的一些测试代码(保存为test_async.py
):
import asyncio
import time
the_status = 'idle'
async def waiting():
global the_status
await asyncio.sleep(0.001)
the_status = 'running'
time.sleep(30)
the_status = 'finished'
def get_status():
global the_status
return the_status
async def main():
loop.create_task(waiting())
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
我通过打开Python控制台并键入以下命令来运行此命令:
from test_async import *
我期望发生的事情是它将开始运行waiting()
,将the_status
更改为“ running”,然后等待30秒,然后再将状态更改为“ finish”。同时,我应该回到控制台提示符,并且可以通过键入get_status()
来获取当前状态。
实际上发生的是变量the_status
从未从其初始状态'idle'改变。
我做错什么了吗?异步不是我要做什么的答案吗?
我的Python版本是3.6。
答案 0 :(得分:1)
我做错什么了吗?
代码有两个问题:
main
仅创建任务而无需等待-您可以将create_task
视为创建“后台”任务。但是在异步环境中,任务仅在主循环中运行,因此run_until_complete(main())
立即退出,因为main()
在创建任务后立即返回。随着主循环的停止,waiting
任务没有机会开始执行。
waiting
调用time.sleep
,这在asyncio中是不允许的。 Asyncio是一个协作式多任务处理系统,用于JS样式的回调和协程,它们在等待阻塞的内容时会自行挂起。 time.sleep
不会挂起,只会阻塞整个事件循环线程。通过run_in_executor
可以正确地在asyncio内部执行旧版阻止代码。
异步不是我要做什么的答案吗?
如果您需要“在后台”执行某些阻止代码,则应使用线程。
import time, concurrent.futures
the_status = 'idle'
def waiting():
global the_status
time.sleep(0.001)
the_status = 'running'
time.sleep(30)
the_status = 'finished'
executor = concurrent.futures.ThreadPoolExecutor()
executor.submit(waiting)
导入代码按预期工作:
>>> import thr2
>>> thr2.the_status
'running'