我一遍又一遍地阅读“Luciano Ramalho”的“Fluent Python”,但我无法理解 asyncio.sleep 在 asyncio 中的行为。
书中有一段说:
永远不要在 asyncio 协程中使用 time.sleep 除非你想阻塞主线程,从而冻结事件循环和整个应用程序。(...) 它应该从 asyncio.sleep(DELAY) 产生。
另一方面:
Python 标准库中的每个阻塞 I/O 函数都会释放 GIL (...) time.sleep() 函数也释放 GIL。
随着 time.sleep() 释放 GIL 代码,其他线程可以运行,但会阻塞当前线程。由于 asyncio 是单线程的,我知道 time.sleep 会阻塞 asyncio 循环。
但是, asyncio.sleep() 如何不阻塞线程?是否可以不延迟事件循环并同时等待?
通常在 IO 操作中我们用来iter()读取哨兵值:
from sys import stdout
with open(r"Z:\github\StackOverFlow\temp.json", "r") as fp:
for chunk in iter(lambda :fp.read(64), ""):
stdout.write(chunk)
Run Code Online (Sandbox Code Playgroud)
iter()但是除了for waitable之外还有其他选择吗asyncio.Queue.get()?
from sys import stdout
with open(r"Z:\github\StackOverFlow\temp.json", "r") as fp:
for chunk in iter(lambda :fp.read(64), ""):
stdout.write(chunk)
Run Code Online (Sandbox Code Playgroud)
当然,这不会起作用,因为它需要可调用,await不能在非异步函数内调用。
情况不允许queue.get_nowait(),因为队列大部分时间都是空的。
简单的修复方法是使用while循环:
for val in iter(lambda: await queue.get(), sentinel):
queue.task_done()
print(val)
Run Code Online (Sandbox Code Playgroud)
但我担心这是否会损害可读性和清晰度。