为什么打印不能与异步生成器一起正常工作?
Why print doesn't work correctly with async generator?
我尝试使用 print 来打印这些值,但它只有在异步生成器完全耗尽后才能工作
import asyncio
import logging
logging.basicConfig(
format='[%(asctime)s]\t%(levelname)s\t%(filename)s:%(lineno)d\t%(message)s',
level=logging.INFO
)
async def range_stream(length, interval=1):
for i in range(length):
yield i
await asyncio.sleep(interval)
async def infinite_stream(interval=1):
i = 0
while True:
yield i
await asyncio.sleep(interval)
i += 1
async def main():
logging.info('Start range stream')
async for i in range_stream(5):
logging.info(i)
print(i)
# logging.info('Start infinite stream')
# async for i in infinite_stream():
# logging.info(i)
# print(i)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
我收到以下输出:
[2019-03-09 09:41:11,271] INFO tmp.py:25 Start range stream
[2019-03-09 09:41:11,271] INFO tmp.py:27 0
[2019-03-09 09:41:12,273] INFO tmp.py:27 1
[2019-03-09 09:41:13,275] INFO tmp.py:27 2
[2019-03-09 09:41:14,277] INFO tmp.py:27 3
[2019-03-09 09:41:15,279] INFO tmp.py:27 4
0
1
2
3
4
第一个打印仅在最后一个 logger.info 之后有效。
如果添加无限异步生成器,则根本不会执行打印:
[2019-03-09 10:04:21,113] INFO tmp.py:25 Start range stream
[2019-03-09 10:04:21,113] INFO tmp.py:27 0
[2019-03-09 10:04:22,114] INFO tmp.py:27 1
[2019-03-09 10:04:23,117] INFO tmp.py:27 2
[2019-03-09 10:04:24,118] INFO tmp.py:27 3
[2019-03-09 10:04:25,120] INFO tmp.py:27 4
[2019-03-09 10:04:26,121] INFO tmp.py:30 Start infinite stream
[2019-03-09 10:04:26,122] INFO tmp.py:32 0
[2019-03-09 10:04:27,123] INFO tmp.py:32 1
[2019-03-09 10:04:28,125] INFO tmp.py:32 2
[2019-03-09 10:04:29,126] INFO tmp.py:32 3
[2019-03-09 10:04:30,128] INFO tmp.py:32 4
[2019-03-09 10:04:31,130] INFO tmp.py:32 5
[2019-03-09 10:04:32,133] INFO tmp.py:32 6
[2019-03-09 10:04:33,134] INFO tmp.py:32 7
[2019-03-09 10:04:34,136] INFO tmp.py:32 8
...
为什么会这样?在打印功能和日志记录模块中使用标准输出之间的根本区别是什么?这是错误吗?
UPD:感谢 user4815162342 的想法 - 此行为仅在 docker 环境的情况下重现,并且仅当您未在 docker 上指定 -it 标志时才会重现 运行 命令并使用默认流进行日志记录 (stderr) 和打印 (stdout)。所以也许这是很正常的行为。
我无法通过 运行ning 您的程序来重现该行为 - 对我来说,print 生成的纯数字行与日志行混合在一起。如果程序 运行 在将其输出重定向到管道的环境中,您将需要显式刷新行以使它们立即出现:
print(..., flush=True)
我尝试使用 print 来打印这些值,但它只有在异步生成器完全耗尽后才能工作
import asyncio
import logging
logging.basicConfig(
format='[%(asctime)s]\t%(levelname)s\t%(filename)s:%(lineno)d\t%(message)s',
level=logging.INFO
)
async def range_stream(length, interval=1):
for i in range(length):
yield i
await asyncio.sleep(interval)
async def infinite_stream(interval=1):
i = 0
while True:
yield i
await asyncio.sleep(interval)
i += 1
async def main():
logging.info('Start range stream')
async for i in range_stream(5):
logging.info(i)
print(i)
# logging.info('Start infinite stream')
# async for i in infinite_stream():
# logging.info(i)
# print(i)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
我收到以下输出:
[2019-03-09 09:41:11,271] INFO tmp.py:25 Start range stream
[2019-03-09 09:41:11,271] INFO tmp.py:27 0
[2019-03-09 09:41:12,273] INFO tmp.py:27 1
[2019-03-09 09:41:13,275] INFO tmp.py:27 2
[2019-03-09 09:41:14,277] INFO tmp.py:27 3
[2019-03-09 09:41:15,279] INFO tmp.py:27 4
0
1
2
3
4
第一个打印仅在最后一个 logger.info 之后有效。
如果添加无限异步生成器,则根本不会执行打印:
[2019-03-09 10:04:21,113] INFO tmp.py:25 Start range stream
[2019-03-09 10:04:21,113] INFO tmp.py:27 0
[2019-03-09 10:04:22,114] INFO tmp.py:27 1
[2019-03-09 10:04:23,117] INFO tmp.py:27 2
[2019-03-09 10:04:24,118] INFO tmp.py:27 3
[2019-03-09 10:04:25,120] INFO tmp.py:27 4
[2019-03-09 10:04:26,121] INFO tmp.py:30 Start infinite stream
[2019-03-09 10:04:26,122] INFO tmp.py:32 0
[2019-03-09 10:04:27,123] INFO tmp.py:32 1
[2019-03-09 10:04:28,125] INFO tmp.py:32 2
[2019-03-09 10:04:29,126] INFO tmp.py:32 3
[2019-03-09 10:04:30,128] INFO tmp.py:32 4
[2019-03-09 10:04:31,130] INFO tmp.py:32 5
[2019-03-09 10:04:32,133] INFO tmp.py:32 6
[2019-03-09 10:04:33,134] INFO tmp.py:32 7
[2019-03-09 10:04:34,136] INFO tmp.py:32 8
...
为什么会这样?在打印功能和日志记录模块中使用标准输出之间的根本区别是什么?这是错误吗?
UPD:感谢 user4815162342 的想法 - 此行为仅在 docker 环境的情况下重现,并且仅当您未在 docker 上指定 -it 标志时才会重现 运行 命令并使用默认流进行日志记录 (stderr) 和打印 (stdout)。所以也许这是很正常的行为。
我无法通过 运行ning 您的程序来重现该行为 - 对我来说,print 生成的纯数字行与日志行混合在一起。如果程序 运行 在将其输出重定向到管道的环境中,您将需要显式刷新行以使它们立即出现:
print(..., flush=True)