Python上下文管理器中换行问题

4
使用Python的contextmanager,我想生成一个包装器来显示某个代码块的类似于Linux的进度:

正在执行某些操作...完成。[42毫秒]

这个方法已经可以工作了 - 有点意思:

from contextlib import contextmanager
import time

@contextmanager
def msg(m):
    print(m + "... ", end='')
    t_start = time.time()
    yield
    t_duration_ms = 1000 * (time.time() - t_start)
    print("done. [{:.0f} ms]".format(t_duration_ms))

这个使用示例应该打印出 "Doing something... ",不换行,等待一秒钟,打印出 "done. [1000 ms]",包括一个换行符并退出。
with msg("Doing something"):
    time.sleep(1)

然而,当运行这段代码时,输出首先等待一秒钟,然后打印整行。如果在第一个print()语句中删除end='',则一切都按预期工作,但代价是丑陋的输出。
为什么会出现这种情况,这是故意的吗?如何避免这种行为?
(Python 3.4.0在Linux Mint 17.1上)
1个回答

4
问题可能是由于 stdout 的缓冲导致的。您需要手动刷新以显示消息。在 Python 3.3+ 中,print 函数具有一个 flush 参数:
from contextlib import contextmanager
import time

@contextmanager
def msg(m):
    print(m + "... ", end='', flush=True)
    t_start = time.time()
    yield
    t_duration_ms = 1000 * (time.time() - t_start)
    print("done. [{:.0f} ms]".format(t_duration_ms))

在3.3版本之前,您需要使用stdoutflush方法:

print(m + "... ", end='')
sys.stdout.flush()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接