3

我试图在这里遵循这个答案:https ://stackoverflow.com/a/5087695/343381

我需要在单个环境中执行多个 bash 命令。我的测试用例很简单:

import subprocess
cmd = subprocess.Popen(['bash'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

# Write the first command
command = "export greeting=hello\n"
cmd.stdin.write(command)
cmd.stdin.flush() # Must include this to ensure data is passed to child process
result = cmd.stdout.read()
print result

# Write the second command
command = "echo $greeting world\n"
cmd.stdin.write(command)
cmd.stdin.flush() # Must include this to ensure data is passed to child process
result = cmd.stdout.read()
print result

我期望发生的事情(基于引用的答案)是我看到打印了“hello world”。实际发生的是它挂在第一个上cmd.stdout.read(),并且永远不会返回。

谁能解释为什么cmd.stdout.read()永远不会回来?

笔记:

  • 在同一环境中从 python 运行多个 bash 命令是绝对必要的。因此, subprocess.communicate() 没有帮助,因为它等待进程终止。
  • 请注意,在我的真实测试用例中,它不是要执行的 bash 命令的静态列表。逻辑更加动态。我没有一次运行所有这些的选项。
4

1 回答 1

2

你在这里有两个问题:

  1. 您的第一个命令不会产生任何输出。所以第一次读块等待一些。
  2. 您正在使用 read() 而不是 readline() - read() 将阻塞,直到有足够的数据可用。

以下修改后的代码(使用 Martjin 的投票建议更新)工作正常:

import subprocess
import select

cmd = subprocess.Popen(['bash'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

poll = select.poll()
poll.register(cmd.stdout.fileno(),select.POLLIN)

# Write the first command
command = "export greeting=hello\n"
cmd.stdin.write(command)
cmd.stdin.flush() # Must include this to ensure data is passed to child process
ready = poll.poll(500)
if ready:
   result = cmd.stdout.readline()
   print result

# Write the second command
command = "echo $greeting world\n"
cmd.stdin.write(command)
cmd.stdin.flush() # Must include this to ensure data is passed to child process
ready = poll.poll(500)
if ready:
   result = cmd.stdout.readline()
   print result

以上有 500 毫秒超时 - 根据您的需要进行调整。

于 2013-03-20T21:55:48.850 回答