【问题标题】:Use python subprocess Popen to touch a file使用 python 子进程 Popen 触摸文件
【发布时间】:2020-11-30 08:24:53
【问题描述】:

我是子进程模块的新手,想知道为什么第一个子进程失败而第二个子进程工作。我在 py3.7 和 macOS 上。

>>> from subprocess import PIPE, Popen, STDOUT
>>> Popen(['touch', '/Users/me/fail.txt'], stdout=PIPE, stderr=STDOUT, shell=True)
>>> Popen(['touch /Users/me/ok.txt'], stdout=PIPE, stderr=STDOUT, shell=True)

【问题讨论】:

    标签: python macos subprocess touch


    【解决方案1】:

    根据docs

    shell 参数(默认为 False)指定是否使用 shell 作为程序来执行。 如果shell is True,建议将args作为字符串而不是序列传递。

    POSIXshell=True 上,shell 默认为/bin/sh。如果 args 是字符串,则该字符串指定要通过 shell 执行的命令。这意味着字符串的格式必须与在 shell 提示符下键入时的格式完全相同。这包括,例如,引用或反斜杠转义文件名,其中包含空格。 如果 args 是一个序列,第一项指定命令字符串,任何附加项将被视为 shell 本身的附加参数。也就是说,Popen 相当于:

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

    所以在第一种情况下,列表的第二个元素作为参数传递给/bin/sh 本身,而不是 touch 命令。所以你基本上是在运行:

    user@name ~$ touch
    

    这会产生以下错误:

    touch: missing file operand
    Try 'touch --help' for more information.
    

    如果您阅读第一个命令的stdout,您会发现相同:

    >>> Popen(['touch', '/Users/me/fail.txt'], stdout=PIPE, stderr=STDOUT, shell=True).stdout.read()
    b"touch: missing file operand\nTry 'touch --help' for more information.\n"
    

    所以虽然shell=True,还是传字符串比较好。

    【讨论】:

      【解决方案2】:

      在高级函数subprocess.run 中,您需要将参数作为列表传递,但对于低级函数Popen,需要直接命令,因此第一个失败但第二个工作。

      【讨论】:

        猜你喜欢
        • 2018-12-05
        • 1970-01-01
        • 1970-01-01
        • 2014-09-15
        • 1970-01-01
        • 2012-09-18
        • 2015-07-05
        相关资源
        最近更新 更多