sys.stdout.write \ r回车,如何覆盖所有字符?

时间:2018-09-17 14:43:19

标签: python python-3.x

我正在使用itertools.cycle,正在使用一个简单的列表作为输入。然后,我编写一个while循环,当我遍历它们时,我想基本上用每种颜色覆盖我的输出。 sys.stdout.write('\r' + colors)行不会覆盖所有字符,仅覆盖下一种颜色的字符串的长度。最后,每次迭代之间有0.5秒的延迟。

import itertools
import time
colors = ['green', 'yellow', 'red']
traffic_light = itertools.cycle(colors)
while True:
    sys.stdout.write('\r' + next(traffic_light))
    sys.stdout.flush()
    time.sleep(.5)

当我在循环中到达“黄色”时,当打印较短的“绿色”和“红色”字符串时,我留下“ w”或“ low”。我的输出看起来像这样(在打印“黄色”的第一个循环之后)。

redlow
greenw
yellow

我可以用'\r'笔架完全覆盖输出吗?

3 个答案:

答案 0 :(得分:3)

您可以计算颜色字符串的最大宽度,然后使用str.ljust在输出中填充足够的空格以填充到最大宽度:

import itertools
import time
import sys
colors = ['green', 'yellow', 'red']
traffic_light = itertools.cycle(colors)
max_width = max(map(len, colors))
while True:
    sys.stdout.write('\r' + next(traffic_light).ljust(max_width))
    sys.stdout.flush()
    time.sleep(.5)

答案 1 :(得分:3)

回车'\r'将把光标发送到该行的开头,在这里可以覆盖现有文本。您可以将其与CSI K序列结合使用,后者将从当前光标擦除到行尾。

只需将\r替换为\r\x1b[K。参见ANSI escape code

import itertools
import sys
import time
colors = ['green', 'yellow', 'red']
traffic_light = itertools.cycle(colors)
while True:
    sys.stdout.write('\r\x1b[K' + next(traffic_light))
    sys.stdout.flush()
    time.sleep(.5)

尝试以下其他转义序列:

# Add color
colors = ['\x1b[32mgreen', '\x1b[33myellow', '\x1b[31mred']

请注意该技术的局限性...如果终端机太短而无法自动换行,则每次打印时程序都会向前移动一行。如果您需要更强大的功能,curses可为您提供更多功能,但在Windows上无法立即使用。

答案 2 :(得分:0)

创建一个左对齐至最大宽度的格式字符串。

import itertools
import time

colors = ['green', 'yellow', 'red']
fmt = f'\r{{:<{max(map(len, colors))}}}' # fmt = '{:<7}'

for color in itertools.cycle(colors):
    print(fmt.format(color), end='') # if needed add: flush=True
    time.sleep(.5)

3.6之前的版本使用fmt = '\r{{:<{}}}'.format(max(map(len, colors)))

或者使用.ljust()字符串方法:

import itertools
import time

colors = ['green', 'yellow', 'red']
width = max(map(len, colors))

for color in itertools.cycle(colors):
    print('\r' + color.ljust(width), end='') # if needed add: flush=True
    time.sleep(.5)