python - 关于 asyncio 的说明

标签 python python-asyncio

我正在尝试了解 python asyncio。

from datetime import datetime
import asyncio


def print_time(number, loop):
    et = loop.time() + 10.0
    while True:
        print('loop {} time {}'.format(number, datetime.now()))
        if (loop.time() >= et):
            break
        yield from asyncio.sleep(3)


loop = asyncio.get_event_loop()

asyncio.ensure_future(print_time(1,loop))
asyncio.ensure_future(print_time(2,loop))

loop.run_forever()

输出(来自 Jupyter 笔记本)

loop 1 time 2017-06-11 21:38:47.398280
loop 2 time 2017-06-11 21:38:47.398452
loop 1 time 2017-06-11 21:38:50.401818
loop 2 time 2017-06-11 21:38:50.402335
loop 1 time 2017-06-11 21:38:53.405770
loop 2 time 2017-06-11 21:38:53.406243
loop 1 time 2017-06-11 21:38:56.409524
loop 2 time 2017-06-11 21:38:56.410034
loop 1 time 2017-06-11 21:38:59.413300
loop 2 time 2017-06-11 21:38:59.413846

我对上述程序有以下疑问

  1. 在这种情况下,函数print_time被视为协程(如包含yield语句?

  2. ensure_future() 每次调用时都会创建一个单独的任务/进程吗?从这个意义上说,它类似于 fork()

  3. 当前循环将永远运行。比如说 10 次迭代后,如何优雅地退出?

最佳答案

  1. In this case is the function print_time considered a coroutine (as in contains yield statement?

您可以在需要时从函数创建协程(例如,如果它应该等待另一个协程)。至create协程你应该使用特殊的装饰器 @asyncio.coroutine (或者在 Python 3.5+ 中使用 async def 定义协程):

@asyncio.coroutine
def print_time(number, loop):
    ...

在您的情况下,生成器被视为协程,只是因为 asyncio 的协程是使用生成器实现的。您不应使用常规生成器作为协程,而应始终显式使用装饰器 @asyncio.coroutine (或 async def)来创建协程。

  1. does ensure_future() creates a separate task/process each time it is called? In that sense is it analogous to fork()

ensure_future 不会创建操作系统线程或进程。通常,所有协程/任务都在单个操作系统线程、单个进程中运行。

ensure_future 是一种规则异步脚本执行流程的方法。当您只是等待某个协程时,它下面的代码只有在协程完成后才会运行。 ensure_future 允许您"run coroutine in background"而不阻止其下面的代码执行。

示例1:

yield from coro_1()
yield from coro_2()  # this line would be started only after coro_1 finished.

示例2:

asyncio.ensure_future(coro_1())
yield from coro_2()  # this line would be started immediately.
                     # coro_1 and coro_2 would de facto run parallely.
  1. The current loop is running for ever. How do I gracefully exit after say 10 iterations.?

您有多种方法可以做到这一点,具体取决于您希望代码如何工作。

例如,这是一个:

from datetime import datetime
import asyncio


# We should somehow limit number of iterations for this coroutine.
# For example we can pass it as param 'tries':
@asyncio.coroutine
def print_time(number, loop, tries):
    et = loop.time() + 10.0
    for _ in range(tries):
        print('loop {} time {}'.format(number, datetime.now()))
        if (loop.time() >= et):
            break
        yield from asyncio.sleep(3)


@asyncio.coroutine
def main():

    # Run to tasks parallely and await both done using 'asyncio.gather':
    yield from asyncio.gather(
        asyncio.ensure_future(print_time(1, loop, tries=5)),
        asyncio.ensure_future(print_time(2, loop, tries=5))
    )


loop = asyncio.get_event_loop()

# Use 'run_until_complete' to finish execution when some coroutine is done:
loop.run_until_complete(main())

输出:

loop 1 time 2017-06-11 15:16:03.864059
loop 2 time 2017-06-11 15:16:03.864059
loop 1 time 2017-06-11 15:16:06.864826
loop 2 time 2017-06-11 15:16:06.864826
loop 1 time 2017-06-11 15:16:09.865046
loop 2 time 2017-06-11 15:16:09.865046
loop 1 time 2017-06-11 15:16:12.865199
loop 2 time 2017-06-11 15:16:12.865199
loop 1 time 2017-06-11 15:16:15.865978
loop 2 time 2017-06-11 15:16:15.865978
[Finished in 12.2s]

关于python - 关于 asyncio 的说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44482416/

相关文章:

python - Django REST Framework 序列化 ForeignKey 和 ManyToManyFields

python - asyncio无法连接到RabbitMQ

Python - asyncio - 从未检索到任务异常

python - 将 TensorFlow Checkpoint 部署到 Google Cloud Platform

python - 无 initscrip 名称控制台 - CX_freeze

javascript - iPython/Jupyter 笔记本 : How to Embed Interactive Graph Using Desmos API?

python - 异步和无限循环

python - 异步 : collecting results from an async function in an executor

python - 异步: multiplexing messages over single websocket connection

python - np.linalg.norm(a-b) 和 np.sqrt(np.sum(np.square(a-b))) 之间的区别?