【问题标题】:Running shell commands from Python and printing the output in real time从 Python 运行 shell 命令并实时打印输出
【发布时间】:2018-07-24 03:59:40
【问题描述】:

我想写一个函数,一次执行多个shell命令,并实时打印shell返回的内容。

我目前有以下不打印 shell 的代码(我使用的是 Windows 10 和 python 3.6.2):

commands = ["foo", "foofoo"]
p = subprocess.Popen("cmd.exe", shell=True, stdin=subprocess.PIPE, \
                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for command in commands:
    p.stdin.write((command + "\n").encode("utf-8"))
p.stdin.close()
p.stdout.read()

如何实时查看 shell 返回的内容?

编辑:这个问题不是 cmets 中前两个链接的重复,它们无助于实时打印

【问题讨论】:

标签: python shell subprocess


【解决方案1】:

我相信你需要这样的东西

commands = ["foo", "foofoo"]
p = subprocess.Popen("cmd.exe", shell=True, stdin=subprocess.PIPE, \
                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for command in commands:
    p.stdin.write((command + "\n").encode("utf-8"))
out, err = p.communicate()
print("{}".format(out))
print("{}".format(err))

【讨论】:

    【解决方案2】:

    假设您想要控制 Python 代码中的输出,您可能需要执行类似的操作

    import subprocess
    
    def run_process(exe):
        'Define a function for running commands and capturing stdout line by line'
        p = subprocess.Popen(exe.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        return iter(p.stdout.readline, b'')
    
    
    if __name__ == '__main__':
        commands = ["foo", "foofoo"]
        for command in commands:
            for line in run_process(command):
                print(line)
    

    【讨论】:

      【解决方案3】:

      可以在不同的线程中处理stdinstdout。这样,一个线程可以处理来自stdout 的打印输出,而另一个线程可以在stdin 上编写新命令。但是,由于stdinstdout 是独立的流,我认为这不能保证流之间的顺序。不过,对于当前示例,它似乎按预期工作。

      import subprocess
      import threading
      
      def stdout_printer(p):
          for line in p.stdout:
              print(line.rstrip())
      
      commands = ["foo", "foofoo"]
      p = subprocess.Popen("cmd.exe", stdin=subprocess.PIPE, 
                           stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                           universal_newlines=True)
      
      t = threading.Thread(target=stdout_printer, args=(p,))
      t.start()
      
      for command in commands:
          p.stdin.write((command + "\n"))
          p.stdin.flush()
      
      p.stdin.close()
      t.join()
      

      另外,请注意我正在逐行编写stdout,这通常是可以的,因为它往往会被缓冲并一次生成一行(或更多行)。我想如果可以的话,可以逐个字符地处理无缓冲的stdout 流(或例如stderr)。

      【讨论】:

      • 这也应该有一个 stderr_printer 线程,否则如果子进程尝试对其 stderr 进行阻塞写入,它可能会挂起。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-21
      • 2021-07-26
      • 1970-01-01
      • 2014-10-05
      • 1970-01-01
      • 2022-08-12
      • 2018-07-30
      相关资源
      最近更新 更多