【问题标题】:Debugging a subprocess.Popen call调试 subprocess.Popen 调用
【发布时间】:2010-02-05 10:05:27
【问题描述】:

我过去一直在成功使用subprocess.Popen,在使用 python 脚本包装二进制文件以格式化参数/自定义等时...

开发第 n 个包装器,我照常进行...但没有任何反应。

这是小代码:

print command
p = subprocess.Popen(command, shell = True)
result = p.communicate()[0]
print vars(p)
return result

这是输出:

/usr/bin/sh /tmp/run/launch.sh
{'_child_created': True, 'returncode': 0, 'stdout': None, 'stdin': None, 'pid': 21650, 'stderr': None, 'universal_newlines': False}

如您所见,目标是创建一个 shell 脚本来设置我需要的所有内容,然后执行它。我更喜欢使用真正的python代码,但不幸的是launch.sh调用了我不想尝试和复制的第3方shell脚本(尽管我已经坚持使用python api一年多了)。

问题是:

  • shell 脚本未执行(它应该产生进程并输出一些小东西)
  • 没有引发 python 异常
  • p 对象中没有任何内容表明发生了错误

我试过check_call也没有成功...

我不知道该怎么做,如果有人能指出我的错误或指导我解决问题,我会非常高兴......

编辑:

  • 尝试在 Linux (sh) 上运行它
  • shell 是调用脚本中的变量替换所必需的

编辑 2:

根据badp 的建议,我调整了代码并添加了

subprocess.Popen('ps', shell = True).communicate()

在创建进程的p = ... 行之后,输出如下:

/usr/bin/sh /tmp/run/launch.sh
  PID TTY          TIME CMD
29978 pts/0    00:00:01 zsh
 1178 pts/0    00:00:01 python
 1180 pts/0    00:00:00 sh <defunct>
 1181 pts/0    00:00:00 ps
None

显然进程已启动(即使&lt;defunct&gt;),还应注意我在传递参数时遇到了一点问题......

谢谢。

【问题讨论】:

  • 你确定脚本实际上没有启动吗?您可以在拨打Popen 后立即尝试在/proc/child-pid-goes-here/ 上拨打stat 来检查这一点
  • command的值是多少?
  • 值在输出/usr/bin/sh /tmp/run/launch.sh的开头打印
  • 目前我有一个非常简单的解决方法:我在launch.sh 文件的开头添加了#!/usr/bin/sh,并将命令替换为/tmp/run/launch.sh。这行得通。如果我也使用shell = True,难道我不应该明确声明sh ...

标签: python subprocess


【解决方案1】:

感谢badp 和他的调试建议,我终于找到了问题的答案。

来自subprocess module上的python页面:

executable 参数指定要执行的程序。很少需要它:通常,要执行的程序由 args 参数定义。如果shell=Trueexecutable 参数指定使用哪个shell。在 Unix 上,默认的 shell 是/bin/sh。在 Windows 上,默认 shell 由 COMSPEC 环境变量指定。您需要在Windows 上指定shell=True 的唯一原因是您希望执行的命令实际上是内置在shell 中的,例如dircopy。您不需要shell=True 来运行批处理文件,也不需要运行基于控制台的可执行文件。

由于我在 Linux 上并使用 shell=True,我的命令实际上是由 executable 执行的参数列表,默认为 /bin/sh。因此执行的完整命令是:/bin/sh /usr/bin/sh /tmp/run/launch.sh... 效果不太好。

我应该使用任何一个:

subprocess.Popen('/tmp/run/launch.sh', shell=True)

subprocess.Popen('/tmp/run/launch.sh', executable = '/usr/bin/sh', shell=True)

shell=True 实际上只会在 Linux 上修改默认的 executable 值,这很棘手...

【讨论】:

  • 将此标记为已接受的答案,然后 :) (不,您没有得到任何代表。)
  • Rep 对我来说并不重要 :) 但是有一个安全性:几天前我不能接受自己的答案。不过我忘了给你的回复点赞,我会改正的。
  • 我遇到了一个相关的问题,发现删除“shell=True”可以将位置参数正常传递给我的 .sh 脚本。否则它试图运行 /bin/sh -c blah.sh param1 。在我的机器上 -c 需要一个字符串。如果我像这样手动运行它: /bin/sh -c "blah.sh param1" 它会起作用。为什么要添加 /bin/sh -c?因为启用了 shell=True 参数。如果不需要,请关闭它。
【解决方案2】:

试试这个:

p = subprocess.Popen(command,
                     shell = True, #is this even needed?
                     stdin = subprocess.PIPE,
                     stdout = subprocess.PIPE,
                   # stderr = subprocess.STDOUT #uncomment if reqd
                    )

使用ping 命令在 Windows 上进行测试。这可以让您communicate,这可能会帮助您找出为什么脚本没有首先启动:)

【讨论】:

  • ping 工作正常,谢谢,问题出在这个特定的命令上。 shell 也是必要的,因为我需要从我的 shell 环境的变量中受益。
猜你喜欢
  • 2012-07-12
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多