【问题标题】:Python not executing a shell command that uses variablePython不执行使用变量的shell命令
【发布时间】:2017-10-03 21:38:25
【问题描述】:

我正在尝试使用 shell 命令从中提取一个变量,我想在我的 python 程序的其余部分中使用它。例如,此代码尝试使用subprocess.callos.system。前者给我一个错误,而后者不会产生任何东西,而如果我不在我的 shell 命令中使用变量,两者都可以正常工作。

import subprocess
import os
# ...

x="05/May/2017"

print 'Date =',x

subprocess.call(['echo Hello World from method 1'], shell=True)
os.system('echo Hello World from method 2')

print "Month from method 1 ="
subprocess.call(['echo $x | cut -f2 -d/'])


print "Month from method 2 ="
m=os.system('echo $x | cut -f2 -d/')
print m

问题出在哪里,我该如何解决?

【问题讨论】:

  • x 是 Python 脚本的变量。它不是环境变量。因此,在 shell 中执行时会失败
  • 怎么样 - os.system('echo %s | cut -f2 -d/' %x)
  • 这里根本没有理由使用外部进程。 month = x.split('/')[1]。是否有一个更好的例子可以证明subprocess.call 的正确使用?
  • @chepner 这是更复杂地使用 shell 脚本命令的简化示例(它可能有 sedawk 等以及多个管道)。
  • @kuro 可以,但是m=os.system('echo %s | cut -f2 -d/' %x) 给了我0 而我使用print m

标签: python shell subprocess os.system


【解决方案1】:

如果要将环境变量传递给子进程,则必须将其显式添加到os.environ,如下所示。另一种选择是创建一个新环境并将其传递给.call

import subprocess;
import os;
os.environ['foo'] = "bar";
subprocess.call('echo $foo', shell=True);

在上述情况下,您还需要shell=True,否则subprocess.call 将查找字面上称为echo $foo 的可执行文件。

当然我们可以手动设置命令行参数:

foo = "bar";
subprocess.call(['echo', foo]);

但它不是环境变量。

至于您正在执行的实际调用,我希望您将cut 作为子进程运行只是为了实验,这样的字符串处理最好在 Python 脚本本身中完成。

【讨论】:

  • 糟糕,我在第二行 subprocess.call 中错过了 shell=True。一旦我把它删除了错误。
【解决方案2】:

问题是python变量没有传递给子进程(shell命令)。

简单的解决方案:

m=subprocess.getoutput('echo %s | cut -f2 -d/' % (x,))

'echo %s | cut -f2 -d/' % (x,) 会先让 python 用变量 x 的内容替换 '%s' 然后调用 subprocess.getoutput('echo 05/May/2017 | cut -f2 -d/')

【讨论】:

  • 方法是正确的,但这仍然是对call的错误使用。
  • 好的,如果我们在其中添加shell=True 就可以了。但是,我无法为其分配变量 m,如原始问题所示。
  • 我已经更新了答案,请使用getoutput 而不是call
  • @Ramast 谢谢。我收到'module' object has no attribute 'getoutput' 错误消息。然而,正如@kuro 的评论中提到的,subprocess.check_output 工作得很好。 :)
  • 你在用python2吗?在这种情况下,您需要使用 subprocess.check_output(["/bin/sh", "-c", 'echo 05/May/2017 | cut -f2 -d/']) 代替
最近更新 更多