如何将Python脚本终端输出显示到Kivy脚本的文本框中
解决Kivy中显示子进程终端输出的问题
问题根源及修复点
- Lambda变量捕获错误:循环内的lambda会引用同一个
line变量,导致UI更新时显示的是最后一行内容。通过给lambda添加默认参数捕获当前line值解决。 - 弹窗创建顺序问题:原代码先启动线程再创建弹窗,线程中引用
output_popup可能触发未定义错误。调整为先创建弹窗再启动线程。 - 重复关闭输出流:两次调用
process.stdout.close(),移除重复调用。 - 标题栏未挂载:创建的
title_bar未加入弹窗内容,导致不显示,需添加到popup_content。 - 输出缓冲延迟:子进程stdout默认缓冲,设置
bufsize=0禁用缓冲,同时在main.py的print语句中添加flush=True确保实时输出。
修正后的boot.py代码
def bootEngram(self, instance): try: output_textbox = TextInput( readonly=True, background_color=(0, 0, 0, 1), foreground_color="#55ead4", font_size=14, font_name=fontFile, multiline=True ) command = ["python", "D:\\silverhand\\code\\main.py"] # 禁用输出缓冲,确保实时捕获输出 process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=0) def update_output_text(instance, line): instance.text += line def read_output(): # 读取标准输出,用默认参数捕获当前line值 for line in iter(process.stdout.readline, ''): Clock.schedule_once(lambda dt, l=line: update_output_text(output_textbox, l)) process.stdout.close() # 读取错误输出 for err in iter(process.stderr.readline, ''): Clock.schedule_once(lambda dt, e=err: update_output_text(output_textbox, f"Error: {e}")) process.stderr.close() process.wait() Clock.schedule_once(lambda dt: output_popup.dismiss()) # 先构建弹窗所有组件 popup_content = BoxLayout(orientation="vertical", spacing=10) title_bar = BoxLayout(orientation="horizontal", size_hint_y=None, height=40, padding=(10, 5)) title_label = Label( text="Engram", color="#f3e600", font_name=fontFile, font_size=20, bold=True, halign="left", size_hint_x=1, valign="middle" ) close_button = Button( text="<", size_hint=(None, None), size=(30, 30), background_color=(0, 0, 0, 1), color=(1, 1, 1, 1), bold=True, size_hint_x=None ) close_button.bind(on_press=lambda x: output_popup.dismiss()) title_bar.add_widget(title_label) title_bar.add_widget(close_button) popup_content.add_widget(title_bar) popup_content.add_widget(output_textbox) output_popup = Popup( title="Engram", title_color="#f3e600", title_size=20, title_font=fontFile, size_hint=(0.9, 0.9), separator_color="#c5003c", auto_dismiss=False, content=popup_content ) # 弹窗初始化完成后启动线程 threading.Thread(target=read_output, daemon=True).start() output_popup.open() except Exception as e: print(f"Error: {e}")
main.py配套修改
将main.py中的打印语句修改为:
print("Hello user!", flush=True)
内容的提问来源于stack exchange,提问作者Menotian
相关产品推荐
相关产品推荐

