Aja*_*thi 2 python python-asyncio
我正在Python中学习asyncio,我想尝试使用asyncio。我的目标是连续读取用户的输入并使用该输入创建需要异步运行的作业/任务。
import asyncio
import os
loop = asyncio.get_event_loop()
async def action():
inp = int(input('enter: '))
await asyncio.sleep(inp)
os.system(f"say '{inp} seconds waited'")
async def main():
while True:
await asyncio.ensure_future(action())
try:
asyncio.run(main())
except Exception as e:
print(str(e))
finally:
loop.close()
Run Code Online (Sandbox Code Playgroud)
我搞砸了一些事情,我想知道如何实现它。每次用户输入一个数字时,脚本都需要休眠给定的时间,然后说它已经等待了。整个事情需要同时进行。如果用户输入 100 作为输入,脚本应该启动一个任务休眠 100 秒,但在用户端,它需要在用户输入后立即再次请求输入。
您的代码的主要问题是您input()直接在异步函数中调用。input它本身是一个阻塞函数,在读取换行符或文件结尾之前不会返回。这是一个问题,因为Python异步代码仍然是单线程的,如果存在阻塞函数,则不会执行其他任何操作。在这种情况下,您需要使用run_in_executor。
您的代码的另一个问题(尽管与您的问题没有直接关系)是您混合了调用事件循环的 pre-python3.7 方式和 python3.7+ 方式。根据文档,asyncio.run单独使用。如果你想使用3.7之前的方式调用循环,正确的方法是
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)
或者
loop = asyncio.get_event_loop()
asyncio.ensure_future(main())
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)
while True由于您的 中有 a ,因此和main()之间没有区别。run_until_completerun_forever
最后,在ensure_future()您的main(). 的要点ensure_future是提供“正常”(即非异步)函数一种将事物安排到事件循环中的方法,因为它们不能使用关键字await。使用的另一个原因ensure_future是,如果您想安排许多具有高 io-bounds(例如网络请求)的任务而不等待其结果。既然你正在await调用函数,那么使用 自然就没有意义了ensure_future。
这是修改后的版本:
import asyncio
import os
async def action():
loop = asyncio.get_running_loop()
inp = await loop.run_in_executor(None, input, 'Enter a number: ')
await asyncio.sleep(int(inp))
os.system(f"say '{inp} seconds waited'")
async def main():
while True:
await action()
asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)
在此版本中,在输入用户输入之前,代码执行在await action()和之间交替执行await loop.run_in_executor()。当没有安排其他任务时,事件循环大部分是空闲的。然而,当有事情被调度时(用 模拟await sleep()),那么控制权就会自然地转移到被调度的长时间运行的任务上。
Python 异步编程的一个关键是你必须确保控制权偶尔转移回事件循环,以便其他计划的事情可以运行。await每当遇到an 时就会发生这种情况。在原始代码中,解释器陷入困境input(),永远没有机会返回事件循环,这就是为什么在提供用户输入之前不会执行其他计划任务的原因。
| 归档时间: |
|
| 查看次数: |
6430 次 |
| 最近记录: |