我想运行一个脚本,它基本上显示如下输出:

Installing XXX...               [DONE]

目前,我打印安装XXX…首先,然后打印[完成]。

我怎么能打印安装xxx…和[DONE]在同一行?


关于在同一行上写入新消息,替换之前的内容的具体问题,请参见如何将先前的打印内容覆盖到标准输出?。这里的大多数答案都把这个问题理解为在当前行的末尾写新的文本。

有关使用单个打印一次输出多个内容的问题,请参见如何在同一行上一次性打印多个内容(固定文本和/或变量值)。


当前回答

如果你想覆盖前一行(而不是不断地添加),你可以在print语句的末尾将\r与print()结合使用。例如,

from time import sleep

for i in xrange(0, 10):
    print("\r{0}".format(i)),
    sleep(.5)

print("...DONE!")

将计数0到9,取代控制台中旧的数字。“…DONE!”将与最后一个计数器9打印在同一行。

在OP的情况下,这将允许控制台以“进度条”的形式显示安装完成百分比,您可以在其中定义开始和结束字符的位置,并在两者之间更新标记。

print("Installing |XXXXXX              | 30%"),

其他回答

您应该使用退格'\r'或('\x08')字符返回控制台输出中的先前位置

Python 2 +:

import time
import sys

def backspace(n):
    sys.stdout.write((b'\x08' * n).decode()) # use \x08 char to go back   

for i in range(101):                        # for 0 to 100
    s = str(i) + '%'                        # string for output
    sys.stdout.write(s)                     # just print
    sys.stdout.flush()                      # needed for flush when using \x08
    backspace(len(s))                       # back n chars    
    time.sleep(0.2)                         # sleep for 200ms

Python 3:

import time   

def backline():        
    print('\r', end='')                     # use '\r' to go back


for i in range(101):                        # for 0 to 100
    s = str(i) + '%'                        # string for output
    print(s, end='')                        # just print and flush
    backline()                              # back to the beginning of line    
    time.sleep(0.2)                         # sleep for 200ms

这段代码将在一行中从0%计算到100%。最终值为:

> python test.py
100%

关于这种情况下flush的其他信息:为什么python打印包含'end='参数的语句在while循环中表现不同?

没有一个答案对我有用,因为它们都暂停了,直到遇到新的一行。我写了一个简单的helper:

def print_no_newline(string):
    import sys
    sys.stdout.write(string)
    sys.stdout.flush()

要测试它:

import time
print_no_newline('hello ')
# Simulate a long task
time.sleep(2)
print('world')

“hello”将首先打印出来,并在睡眠前刷新到屏幕上。之后你就可以使用标准打印了。

我找到了这个解决方案,它在Python 2.7上运行

# Working on Python 2.7 Linux

import time
import sys


def backspace(n):
    print('\r', end='')                     # use '\r' to go back


for i in range(101):                        # for 0 to 100
    s = str(i) + '%'                        # string for output
    sys.stdout.write(string)
    backspace(len(s))                       # back for n chars
    sys.stdout.flush()
    time.sleep(0.2)                         # sleep for 200ms

这是一个非常古老的线程,但这里有一个非常彻底的答案和示例代码。

\r是ASCII字符集回车的字符串表示形式。它与八进制015 [chr(0o15)]或十六进制0d [chr(0x0d)]或十进制13 [chr(13)]相同。看man ascii,无聊的阅读。它(\r)是一种相当可移植的表示法,并且易于人们阅读。它非常简单地意味着将打字机上的架子一直移动到起点,而不前进纸张。这是CRLF的CR部分,意思是回车和换行。

print()是Python 3中的一个函数。在Python 2(任何你感兴趣的版本)中,可以通过从__future__模块导入其定义来将print强制导入函数。print函数的好处是,您可以指定在末尾打印什么,覆盖\n的默认行为,在每次print()调用的末尾打印换行符。

sys.stdout.flush tells Python to flush the output of standard output, which is where you send output with print() unless you specify otherwise. You can also get the same behavior by running with python -u or setting environment variable PYTHONUNBUFFERED=1, thereby skipping the import sys and sys.stdout.flush() calls. The amount you gain by doing that is almost exactly zero and isn't very easy to debug if you conveniently forget that you have to do that step before your application behaves properly.

还有一个样本。请注意,这在Python 2或3中运行得很好。

from __future__ import print_function

import sys
import time

ANS = 42
FACTORS = {n for n in range(1, ANS + 1) if ANS % n == 0}

for i in range(1, ANS + 1):
    if i in FACTORS:
        print('\r{0:d}'.format(i), end='')
        sys.stdout.flush()
        time.sleep(ANS / 100.0)
else:
    print()

这个简单的例子将在同一行打印1-10个字符。

for i in range(1,11):
    print (i, end=" ")