Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么命令及其参数必须位于subprocess.Popen的列表中?_Python_Linux_Subprocess - Fatal编程技术网

Python 为什么命令及其参数必须位于subprocess.Popen的列表中?

Python 为什么命令及其参数必须位于subprocess.Popen的列表中?,python,linux,subprocess,Python,Linux,Subprocess,我试过了 import subprocess p = subprocess.Popen("ls -la /etc", stdout=subprocess.PIPE, stderr=subprocess.PIPE) p.stdout.read().decode() 这让我 FileNotFoundError: [Errno 2] No such file or directory: 'ls -la /etc': 'ls -la /etc' 跟随 是的 import subprocess p

我试过了

import subprocess
p = subprocess.Popen("ls -la /etc", stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.stdout.read().decode()
这让我

FileNotFoundError: [Errno 2] No such file or directory: 'ls -la /etc': 'ls -la /etc'

跟随

是的

import subprocess
p = subprocess.Popen(["ls", "-la", "/etc"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.stdout.read().decode()
这确实有效

为什么呢?为什么我必须拆分命令及其参数?这种设计背后的基本原理是什么


Python版本:

3.7.3 (default, Mar 27 2019, 22:11:17)
[GCC 7.3.0]
根据,它取决于
shell=
关键字参数关于字符串与列表的工作方式(粗体表示可能导致您的行为的原因):

args应该是一系列程序参数,或者是单个字符串或类似路径的对象。默认情况下,如果args是序列,则要执行的程序是args中的第一项。如果args是字符串,则解释取决于平台,如下所述。有关与默认行为的其他差异,请参见shell和可执行参数。除非另有说明,否则建议按顺序传递args

在POSIX上,如果args是字符串,则该字符串将被解释为要执行的程序的名称或路径。但是,只有在不向程序传递参数的情况下才能执行此操作。

再往下

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

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

在shell=True的Windows上,COMSPEC环境变量指定默认shell。在Windows上唯一需要指定shell=True的时间是希望执行的命令内置到shell中时(例如dir或copy)。运行批处理文件或基于控制台的可执行文件不需要shell=True

根据,它取决于
shell=
关键字参数关于字符串与列表的工作方式(粗体表示可能导致您的行为的原因):

args应该是一系列程序参数,或者是单个字符串或类似路径的对象。默认情况下,如果args是序列,则要执行的程序是args中的第一项。如果args是字符串,则解释取决于平台,如下所述。有关与默认行为的其他差异,请参见shell和可执行参数。除非另有说明,否则建议按顺序传递args

在POSIX上,如果args是字符串,则该字符串将被解释为要执行的程序的名称或路径。但是,只有在不向程序传递参数的情况下才能执行此操作。

再往下

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

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

在shell=True的Windows上,COMSPEC环境变量指定默认shell。在Windows上唯一需要指定shell=True的时间是希望执行的命令内置到shell中时(例如dir或copy)。运行批处理文件或基于控制台的可执行文件不需要shell=True

这就是UNIX上所有进程调用的工作方式。 在后台,在UNIX上运行程序通常通过以下步骤完成:

  • 关闭子进程
  • 在该子进程中,如果请求重定向,则打开stdin、stdout、stderr等的新副本,使用调用将新打开的文件分配到作为重定向目标的文件描述符上
  • 在该子进程中,使用syscall将当前进程替换为所需的子进程此系统调用采用参数数组,而不是单个字符串。
  • 如果要阻止呼叫,则让孩子退出
  • 因此,
    subprocess.Popen
    公开了数组接口,因为数组接口是操作系统在后台实际执行的操作

    当您在shell上运行
    ls/tmp
    时,该shell会将字符串转换为数组,然后自己执行上述步骤——但它提供了更多的控制(并避免了严重的错误——如果有人创建一个名为
    /tmp/$(rm-rf~)
    的文件,您不希望尝试
    cat/tmp/$(rm-rf~)
    来删除主目录)当您自己进行转换时。

    这就是所有进程调用在UNIX上工作的方式。 在后台,在UNIX上运行程序通常通过以下步骤完成:

  • 关闭子进程
  • 在该子进程中,如果请求重定向,则打开stdin、stdout、stderr等的新副本,使用调用将新打开的文件分配到作为重定向目标的文件描述符上
  • 在该子进程中,使用syscall将当前进程替换为所需的子进程此系统调用采用参数数组,而不是单个字符串。
  • 如果要阻止呼叫,则让孩子退出
  • 因此,
    subprocess.Popen
    公开了数组接口,因为数组接口是操作系统在后台实际执行的操作

    在shell上运行
    ls/tmp
    时,该shell将字符串转换为数组并