从子进程读取的实时stdout仅在从PyCharm而不是Terminal运行时才起作用

时间:2017-04-26 14:49:39

标签: python python-3.x tkinter subprocess pycharm

应用程序的作用:运行子进程并将标准输出实时显示给Tkinter文本框小部件。

当我从PyCharm运行应用程序时,这非常有效。

当我从终端./application.py运行该应用程序时,它不会实时显示,而是会在过程完成后显示所有

一些细节:

我有一个子进程正在运行(子进程每1秒打印一次“垃圾邮件”,持续10秒):

process = subprocess.Popen(<some file path>, stdout=subprocess.PIPE, universal_newlines=True)

我正在将标准输出打印到Tkinter文本框小部件:

for stdout_line in iter(process.stdout.readline, ""):
     self.app.pm_textbox.see(tk.END)
     self.app.pm_textbox.insert(tk.INSERT, stdout_line)

所以我的问题是什么可能导致从终端和PyCharm运行以不同方式显示stdout数据?

1 个答案:

答案 0 :(得分:0)

我知道这是一个旧线程,但是-

我和你有同样的问题。我问了一个question,似乎可以帮助我朝着正确的方向进行实时输出。我的问题是我需要区分CR产生的输出并在程序中模拟该行为。但是后来我也遇到了您的问题-我花了3天的时间试图找到解决此问题的方法。

在阅读this并且对他们所做的事情没有运气之后,我发现此线程没有答案,但是一个comment经过一点修改后终于对我有所帮助。

最终对我有用的是:

#                        This seems to handle    This seems to handle
#                        the terminal output     the PyCharm output
proc = subprocess.Popen(["stdbuf", "-oL"] + cmd, stdout=subprocess.PIPE)

out = io.open(proc.stdout.fileno(), mode='r', encoding="utf-8", newline='')
should_cr = False
for line in out:
    if should_cr is True:
        sys.stdout.write("\r")
        sys.stdout.flush()

    if line.endswith(os.linesep):
        should_cr = False
        sys.stdout.write(line)
        sys.stdout.flush()

    elif line.endswith("\r"):
        should_cr = True
        line = line.rstrip()
        sys.stdout.write(line)
        sys.stdout.flush()

如果您不考虑CR输出,那当然更简单了:

#                        This seems to handle    This seems to handle
#                        the terminal output     the PyCharm output
proc = subprocess.Popen(["stdbuf", "-oL"] + cmd, stdout=subprocess.PIPE)
for line in iter(proc.stdout.readline, ''):
    print(line)

请注意,这在Python 2.7中对我有效