终端输出长字符串时重复打印同一行的原因及解决方法
问题
实现了一个字符串动画打印的Python代码,短字符串运行正常,但字符串长度达到终端宽度时,会开始重复打印同一行。代码如下:
import time import sys def animate_string(input_string, delay_second=0.01): current_string = "" for target_char in input_string: if target_char == '\n': # Print a newline and reset current_string print() current_string = "" continue current_char = 'a' while current_char != target_char: a_code = ord(current_char) # previous string + current letter sys.stdout.write('\r' + current_string + current_char) sys.stdout.flush() time.sleep(delay_second) # Move to the next char (used ASCII) current_char = chr(ord(current_char) + 1) # Handle bound issue if current_char == '{': # After 'z' current_char = 'A' elif current_char == '[': # After 'Z' current_char = target_char # Add the target character to the current string current_string += target_char # Print the updated current string sys.stdout.write('\r' + current_string) sys.stdout.flush() # Print a newline at the end to finish the output cleanly print() animate_string("fjweiofjewoifjweofjewofjewffewjfiowjfwaifjewipfajeehgpwth235r2fjweiofjewoifjweofjewofjewffewjfiowjfwaifjewipfajeehgpwth235r2fjweiofjewoifjweofjewofjewffewjfiowjfwaifjewipfajeehgpwth235r2fjweiofjewoifjweofjewofjewffewjfiowjfwaifjewipfajeehgpwth235r2", 0.0002)
原因分析
当字符串长度超过终端宽度时,终端会自动将溢出内容换行到下一行。但代码中使用的\r(回车符)仅能将光标移到当前物理行的行首,而非整个逻辑行的开头。后续输出会覆盖当前物理行内容,同时之前溢出到下一行的内容不会被清除,视觉上就会呈现重复打印同一行的效果。
解决方案
通过检测终端宽度并处理自动换行逻辑,同时清除行尾残留内容来解决问题。修改后的代码如下:
import time import sys import shutil def animate_string(input_string, delay_second=0.01): current_string = "" # 获取当前终端宽度 terminal_width = shutil.get_terminal_size().columns for target_char in input_string: if target_char == '\n': print() current_string = "" continue current_char = 'a' while current_char != target_char: display_str = current_string + current_char # 超过终端宽度时,只显示最后一行的内容 if len(display_str) > terminal_width: display_str = display_str[-terminal_width:] # 用空格填充整行,清除残留内容 sys.stdout.write(f'\r{display_str.ljust(terminal_width)}') sys.stdout.flush() time.sleep(delay_second) current_char = chr(ord(current_char) + 1) if current_char == '{': # 小写z之后切换到大写A current_char = 'A' elif current_char == '[': # 大写Z之后直接跳到目标字符 current_char = target_char current_string += target_char # 处理整行溢出:打印完整行并截断剩余内容 while len(current_string) >= terminal_width: print(current_string[:terminal_width]) current_string = current_string[terminal_width:] # 显示剩余内容并清除行尾残留 sys.stdout.write(f'\r{current_string.ljust(terminal_width)}') sys.stdout.flush() # 打印最后剩余的内容并换行 print(current_string if current_string else "") animate_string("fjweiofjewoifjweofjewofjewffewjfiowjfwaifjewipfajeehgpwth235r2fjweiofjewoifjweofjewofjewffewjfiowjfwaifjewipfajeehgpwth235r2fjweiofjewoifjweofjewofjewffewjfiowjfwaifjewipfajeehgpwth235r2fjweiofjewoifjweofjewofjewffewjfiowjfwaifjewipfajeehgpwth235r2", 0.0002)
代码说明
- 用
shutil.get_terminal_size()动态获取终端宽度,适配不同窗口大小; - 每次输出时用
ljust(terminal_width)填充空格,确保清除当前行所有残留内容; - 当字符串长度超过终端宽度时,自动截断并打印完整行,剩余部分继续动画输出,模拟终端自然换行逻辑;
- 动画过程中,超过宽度的内容仅显示最后一行部分,符合终端显示习惯。
内容的提问来源于stack exchange,提问作者bluepiplup
相关产品推荐
相关产品推荐

