python 上下文管理器换行问题

python contextmanager newline issue

使用Python的contextmanager我想生成一个包装器来显示Linux-like某个代码块的进度:

Doing something... done. [42 ms]

这是有效的 - 有点:

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)

但是,当 运行 片段时,输出 first 等待一秒钟,然后 afterwards 打印整行.在第一个 print() 语句中删除 end='' 时,一切都按预期工作,但代价是输出丑陋。

为什么会这样,是否有意为之,如何避免这种行为?

(Python 3.4.0 on Linux Mint 17.1)

问题可能是由于 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()