启动异步功能而不导入asyncio包
可以启动这样的功能
async def foo():
while True:
print("Hello!")
没有导入asyncio
包(并获取事件循环)?
我正在寻找一种类似于Go的goroutine的原理,在该原理中,仅需go
声明即可启动协程。
编辑:之所以我不导入asyncio软件包,仅仅是因为我认为应该可以在没有事件循环(明确)的情况下启动协程。我不明白为什么 异步def
和类似的语句是核心语言(甚至是语法的一部分)的一部分,而启动已创建的协程的方法仅通过包提供。
-
当然,
async
无需显式使用即可启动功能asyncio
。毕竟,它asyncio
是用Python编写的,所以它也可以执行所有操作(尽管有时可能需要其他模块,例如selectors
或者threading
如果您打算同时等待外部事件,或者并行执行其他代码)。在这种情况下,由于您的函数
await
内部没有点,因此只需要按一下即可进行操作。您可以通过推协程send
荷兰国际集团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
s取代,多个协程保留在队列中,因此每个协程最终轮流使用,事件更加丰富,包括网络/套接字通信,文件系统读/写,信号处理,线程/进程副执行等。但是基本思想仍然是相同的:您抓取一些协程,将它们从空中传送到另一个空中,直到它们全部升起,然后将它们杂耍起来StopIteration
。当所有协程无关时,您将前往外部世界并获取一些其他事件,让它们继续咀嚼。我希望现在一切都清楚了。:-)