什么是 'async_generator' 以及它与 Python 3.6 中的 'coroutine' 有何不同?
What is an 'async_generator' & how is it different from a 'coroutine' in Python 3.6?
我怀疑这与 b/w yield from
和 await
的差异有关。
但是,除了新的 object 被指定为 async_generator
之外,我不清楚它与 coroutine
之间的区别所带来的后果。
(除了我在标题中提出的问题,我不知道还能问什么...)
import asyncio
async def async_generator_spits_out_letters():
yield 'a'
yield 'b'
yield 'c'
yield 'd'
await asyncio.sleep(0)
async def coroutine_prints_messages():
while True:
print('hi')
await asyncio.sleep(2)
def test_it():
print(type(async_generator_spits_out_letters))
print(type(coroutine_prints_messages))
# This is how I choose to do newlines....it's easier for me to read. :[
print(); print()
print(type(async_generator_spits_out_letters()))
print(type(coroutine_prints_messages()))
这给出:
<class 'async_generator'>
<class 'coroutine'>
<class 'function'>
<class 'function'>
我搞不懂这个...
为了 an async_generator
-producing function to 运行 在事件循环中,它的输出必须包裹在 coroutine.
这是为了防止 async_generator
直接在事件循环中产生值。
import asyncio
# This produces an async_generator
async def xrange(numbers):
for i in range(numbers):
yield i
await asyncio.sleep(0)
# This prevents an async_generator from yielding into the loop.
async def coroutine_wrapper(async_gen, args):
try:
print(tuple([i async for i in async_gen(args)]))
except ValueError:
print(tuple([(i, j) async for i, j in async_gen(args)]))
循环只喜欢任务和未来。
如果一个循环从它的一个任务中接收到一个整数或字符串或..任何不是从 future
派生的东西,它就会中断。
因此 coroutines
必须:
- 产生
future
s(或future
的子类)
- 或者不将任何值传递回循环。
这是 main():
def main():
print('BEGIN LOOP:')
print()
loop = asyncio.get_event_loop()
xrange_iterator_task = loop.create_task(coroutine_wrapper(xrange, 20))
try:
loop.run_until_complete(xrange_iterator_task)
except KeyboardInterrupt:
loop.stop()
finally:
loop.close()
print()
print('END LOOP')
print(); print()
print('type(xrange) == {}'.format(type(xrange)))
print('type(xrange(20) == {}'.format(type(xrange(20))))
print()
print('type(coroutine_wrapper) == {}'.format(type(coroutine_wrapper)))
print('type(coroutine_wrapper(xrange,20)) == {}'.format(type(coroutine_wrapper(xrange, 20))))
if __name__ == '__main__':
main()
这是输出:
BEGIN LOOP:
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
END LOOP
type(xrange) == <class 'function'>
type(xrange(20)) == <class 'async_generator'>
type(coroutine_wrapper) == <class 'function'>
type(coroutine_wrapper(xrange,20)) == <class 'coroutine'>
我怀疑这与 b/w yield from
和 await
的差异有关。
但是,除了新的 object 被指定为 async_generator
之外,我不清楚它与 coroutine
之间的区别所带来的后果。
(除了我在标题中提出的问题,我不知道还能问什么...)
import asyncio
async def async_generator_spits_out_letters():
yield 'a'
yield 'b'
yield 'c'
yield 'd'
await asyncio.sleep(0)
async def coroutine_prints_messages():
while True:
print('hi')
await asyncio.sleep(2)
def test_it():
print(type(async_generator_spits_out_letters))
print(type(coroutine_prints_messages))
# This is how I choose to do newlines....it's easier for me to read. :[
print(); print()
print(type(async_generator_spits_out_letters()))
print(type(coroutine_prints_messages()))
这给出:
<class 'async_generator'>
<class 'coroutine'>
<class 'function'>
<class 'function'>
我搞不懂这个...
为了 an async_generator
-producing function to 运行 在事件循环中,它的输出必须包裹在 coroutine.
这是为了防止 async_generator
直接在事件循环中产生值。
import asyncio
# This produces an async_generator
async def xrange(numbers):
for i in range(numbers):
yield i
await asyncio.sleep(0)
# This prevents an async_generator from yielding into the loop.
async def coroutine_wrapper(async_gen, args):
try:
print(tuple([i async for i in async_gen(args)]))
except ValueError:
print(tuple([(i, j) async for i, j in async_gen(args)]))
循环只喜欢任务和未来。
如果一个循环从它的一个任务中接收到一个整数或字符串或..任何不是从 future
派生的东西,它就会中断。
因此 coroutines
必须:
- 产生
future
s(或future
的子类) - 或者不将任何值传递回循环。
这是 main():
def main():
print('BEGIN LOOP:')
print()
loop = asyncio.get_event_loop()
xrange_iterator_task = loop.create_task(coroutine_wrapper(xrange, 20))
try:
loop.run_until_complete(xrange_iterator_task)
except KeyboardInterrupt:
loop.stop()
finally:
loop.close()
print()
print('END LOOP')
print(); print()
print('type(xrange) == {}'.format(type(xrange)))
print('type(xrange(20) == {}'.format(type(xrange(20))))
print()
print('type(coroutine_wrapper) == {}'.format(type(coroutine_wrapper)))
print('type(coroutine_wrapper(xrange,20)) == {}'.format(type(coroutine_wrapper(xrange, 20))))
if __name__ == '__main__':
main()
这是输出:
BEGIN LOOP:
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
END LOOP
type(xrange) == <class 'function'>
type(xrange(20)) == <class 'async_generator'>
type(coroutine_wrapper) == <class 'function'>
type(coroutine_wrapper(xrange,20)) == <class 'coroutine'>