Python的print语句在带有回车符时不会打印任何内容

7
我正在尝试编写一个简单的工具,它可以从磁盘中读取文件,进行图像处理,并返回算法的结果。由于程序有时需要一些时间来运行,我想要一个进度条,以便了解程序的进行情况。由于我不喜欢在命令行界面上弄乱输出内容,而我又在 Unix 平台上,因此我希望使用 '\r' 字符只在一行上打印进度条。
但是当我运行这段代码时,它没有输出任何内容。

# Files is a list with the filenames
for i, f in enumerate(files):
    print '\r%d / %d' % (i, len(files)),
    # Code that takes a long time

我也尝试过以下方法:

print '\r', i, '/', len(files),

现在为了确保这在Python中可以工作,我尝试了以下代码:


heartbeat = 1
while True:
    print '\rHello, world', heartbeat,
    heartbeat += 1

这段代码完美运行。出了什么问题?我对Linux上的回车符理解是它只会将换行符移到开头,然后我可以覆盖之前写入的旧文本,只要我不在任何地方打印换行符。但是这似乎并没有发生。

另外,在命令行中显示进度条是否有更好的方法,而不是我目前尝试的方式?


3
http://pypi.python.org/pypi/progressbar - kennytm
3个回答

10

尝试在print语句后添加sys.stdout.flush()。可能是print在写入换行符之前不会刷新输出,而这里没有发生。


是的,就是这样。我仍然不完全确定为什么“Hello World”示例有效。它也没有发出换行符。也许是因为打印语句运行足够长时间后,它会在一定数量的字符后自动刷新缓冲区? - Jonathan Sternberg
是的,当缓冲区变满时,它必须已经刷新了缓冲区。 - interjay
另外,也可以使用sys.stderr立即打印到屏幕上。默认情况下,stderr是无缓冲的。 - amphetamachine

2
Linux中处理回车符的方式在终端仿真器之间有很大的不同。
通常,人们会使用终端转义码来告诉终端仿真器如何移动虚拟的“车riage”(想象一下在BBS线路上运行的全屏程序)。我知道的是VT100转义码:
\e[A:向上 \e[B:向下 \e[C:向右 \e[D:向左 \e[1~:home \e[4~:end
其中\e是转义字符,\x1b。
尝试用\e[1~替换所有\r。
另请参见this post

2
如果您的终端是行缓冲的,如果您没有发出换行符,则可能需要使用sys.stdout.flush()才能看到您的打印输出。

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