Python后台线程print输出缩进原因及消除方法咨询
这个问题我之前也碰到过,其实是终端的原始(raw)模式在搞鬼!
为啥会出现缩进?
你写的getch()函数里用了tty.setraw()把终端切换成了raw模式,这个模式下终端会关掉很多默认的"自动处理"功能,其中就包括ONLCR选项——它本来会把输出的换行符\n自动转换成\r\n(回车+换行),让光标回到行首再换行。
- 当程序输出
press any key时,终端还在规范模式,\n被转换成\r\n,光标正常回到下一行开头。 - 但调用
getch()后终端进入raw模式,后台线程的print输出的\n只会让光标向下跳一行,不会回到行首。你看到的"缩进"其实是视觉错觉:后台线程输出内容时,光标还停留在上一行的对应位置,导致新内容看起来像是缩进了,本质是终端显示的光标位置异常。
怎么消除这个缩进?
有几个简单的方案可以解决:
方案1:手动加回车符\r
直接在print的内容后面加上\r,强制光标回到行首,这样输出就正常了:
def do_stuff(): for i in range(5): time.sleep(1) print 'test {}\r'.format(i) # 加个\r就行
方案2:后台线程输出时临时切回规范模式
如果不想改输出内容,可以给后台线程加个上下文管理器,输出前临时把终端切回规范模式,输出完再切回去(要加锁保证线程安全):
import sys, termios, tty, time, threading from contextlib import contextmanager lock = threading.Lock() original_terminal_settings = None # 定义上下文管理器,临时恢复规范模式 @contextmanager def use_normal_terminal(): global original_terminal_settings with lock: fd = sys.stdin.fileno() current_settings = termios.tcgetattr(fd) try: termios.tcsetattr(fd, termios.TCSADRAIN, original_terminal_settings) yield finally: termios.tcsetattr(fd, termios.TCSADRAIN, current_settings) def getch(): global original_terminal_settings fd = sys.stdin.fileno() original_terminal_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, original_terminal_settings) return ch def do_stuff(): for i in range(5): time.sleep(1) with use_normal_terminal(): print 'test {}'.format(i) t = threading.Thread(target=do_stuff, args=[], kwargs={}) t.start() print 'press any key' print getch() print 'done'
方案3:直接用os.write输出\r\n
绕过Python的print自动换行,直接向终端写入带\r\n的内容:
import os def do_stuff(): for i in range(5): time.sleep(1) os.write(sys.stdout.fileno(), 'test {}\r\n'.format(i))
效果验证
用方案1修改后,程序输出就会变成正常的无缩进格式:
press any key test 0 test 1 test 2 test 3 test 4 x done
内容的提问来源于stack exchange,提问作者Jesse Aldridge
相关产品推荐
相关产品推荐

