subprocess.check_call出现奇怪的python错误

时间:2014-09-10 20:30:20

标签: python subprocess python-3.4

我在使用python subprocess.check_call()函数时遇到了一个非常奇怪的错误。这里有两个测试,由于权限问题都应该失败,但第一个只返回'usage'(“意外行为”):

# Test #1
import subprocess
subprocess.check_call(['git', 'clone', 'https://github.com/achedeuzot/project',
                       '/var/vhosts/project'], shell=True)

# Shell output
usage: git [--version] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           [-c name=value] [--help]
           <command> [<args>]

The most commonly used git commands are:
[...]

现在进行第二次测试(“预期行为”):

# Test #2
import subprocess
subprocess.check_call(' '.join(['git', 'clone', 'https://github.com/achedeuzot/project',
                                '/var/vhosts/project']), shell=True)
# Here, we're making it into a string, but the call should be *exactly* the same.

# Shell output
fatal: could not create work tree dir '/var/vhosts/project'.: Permission denied

第二个错误是正确的错误。我确实没有权限。但为什么这两个电话之间有区别?我认为使用单个字符串或列表与check_call()函数相同。我已经阅读了python documentation和各种用法示例,看起来都是正确的。

有人有同样的奇怪错误吗?或者有人知道为什么在命令完全相同时输出会有差异吗?

附注:Python 3.4

2 个答案:

答案 0 :(得分:3)

从第一个中删除shell=True。如果仔细阅读子进程模块文档,您将看到。如果shell=False(默认),则第一个参数是带有参数和all的命令行列表(或者只包含命令的字符串,根本不提供任何参数)。如果shell = True,那么第一个参数是一个表示shell命令行的字符串,执行一个shell,然后为你解析命令行并按空格分割(+更危险的事情,你可能不希望它做)。 如果shell=True且第一个参数是列表,则第一个列表项是shell命令行,其余的作为参数传递给shell,而不是命令

除非你确实真的需要,否则总是让shell=False

答案 1 :(得分:0)

这里是文档中的相关位:

  

如果args是一个序列,则第一个项指定命令字符串,并且任何其他项将被视为shell本身的附加参数。也就是说,Popen相当于:

     

Popen(['/bin/sh', '-c', args[0], args[1], ...])