gpt4 book ai didi

python - 在不导入 asyncio 包的情况下启动异步功能

转载 作者:行者123 更新时间:2023-12-05 07:38:41 25 4
gpt4 key购买 nike

是否可以启动这样的功能

async def foo():
while True:
print("Hello!")

没有导入 asyncio 包(并获取事件循环)?

我正在寻找一种类似于 Go 的 goroutines 的原理,其中可以仅使用 go 语句启动协程。

编辑:我不导入 asyncio 包的原因仅仅是因为我认为应该可以在没有事件循环的情况下启动协程(显式)。我不明白为什么 async def 和类似语句是核心语言的一部分(甚至是语法的一部分),而启动创建的协程的方式只能通过包提供。

最佳答案

当然可以在不显式使用asyncio 的情况下启动async 函数。毕竟,asyncio 是用 Python 编写的,所以它所做的一切,您也可以做到(尽管有时您可能需要其他模块,例如 selectorsthreading 如果您打算同时等待外部事件,或并行执行一些其他代码)。

在这种情况下,由于您的函数内部没有 await 点,因此它只需要一次推送即可开始。您可以通过发送ing None 将协程推送到协程中。

>>> foo().send(None)
Hello!
Hello!
...

当然,如果您的函数(协程)内部有 yield 表达式,它会在每个 yield 点暂停执行,您需要向其中压入额外的值(通过 coro.send(value)next(gen))- 但如果您知道生成器的工作原理,您就已经知道了。

import types

@types.coroutine
def bar():
to_print = yield 'What should I print?'
print('Result is', to_print)
to_return = yield 'And what should I return?'
return to_return

>>> b = bar()
>>> next(b)
'What should I print?'
>>> b.send('Whatever you want')
Result is Whatever you want
'And what should I return?'
>>> b.send(85)
Traceback...
StopIteration: 85

现在,如果您的函数内部有 await 表达式,它会在计算每个表达式时暂停。

async def baz():
first_bar, second_bar = bar(), bar()
print('Sum of two bars is', await first_bar + await second_bar)
return 'nothing important'

>>> t = baz()
>>> t.send(None)
'What should I print?'
>>> t.send('something')
Result is something
'And what should I return?'
>>> t.send(35)
'What should I print?'
>>> t.send('something else')
Result is something else
'And what should I return?'
>>> t.send(21)
Sum of two bars is 56
Traceback...
StopIteration: nothing important

现在,所有这些 .send 都开始变得乏味了。让它们半自动生成会很好。

import random, string

def run_until_complete(t):
prompt = t.send(None)
try:
while True:
if prompt == 'What should I print?':
prompt = t.send(random.choice(string.ascii_uppercase))
elif prompt == 'And what should I return?':
prompt = t.send(random.randint(10, 50))
else:
raise ValueError(prompt)
except StopIteration as exc:
print(t.__name__, 'returned', exc.value)
t.close()

>>> run_until_complete(baz())
Result is B
Result is M
Sum of two bars is 56
baz returned nothing important

恭喜,您刚刚编写了第一个事件循环! (没想到它会发生,是吗?;)当然,它非常原始:它只知道如何处理两种类型的提示,它不会启用 t 来产生额外的协程与它同时运行,并通过 random 生成器伪造事件。

(事实上,如果你想获得哲理:我们在上面手动完成的操作,可以称为事件循环:Python REPL 正在将提示打印到控制台窗口,它依赖于通过在其中键入 t.send(whatever) 来提供事件。:)

asyncio 只是上面的一个非常通用的变体:提示被替换为 Future,多个协程被保留在队列中,所以每个协程最终都会轮到它,事件要丰富得多,包括网络/套接字通信、文件系统读/写、信号处理、线程/进程端执行等。但基本思想仍然相同:您抓取一些协程,在空中玩弄它们,将 Futures 从一个路由到另一个,直到它们都引发 StopIteration。当所有协程都无事可做时,你就去外部世界抓一些额外的事件供它们咀嚼,然后继续。

我希望现在一切都清楚了。 :-)

关于python - 在不导入 asyncio 包的情况下启动异步功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47769612/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com