python - 为什么命令及其参数必须在 subprocess.Popen 的列表中?

标签 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'

关注

Python subprocess.Popen with var/args

我做到了

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]

最佳答案

这就是所有进程调用在 UNIX 上的工作方式。

在幕后,在 UNIX 上运行程序传统上是通过以下步骤完成的:

  1. fork()关闭子进程。
  2. 在该子进程中,如果请求重定向,则打开 stdin、stdout、stderr 等的新副本,使用 dup2()调用以将新打开的文件分配给作为重定向目标的文件描述符。
  3. 在该子进程中,使用 execve()系统调用以用所需的子进程替换当前进程。 此系统调用采用参数数组,而不是单个字符串。
  4. wait()如果调用是阻塞的,则让 child 退出。

因此,subprocess.Popen 公开了数组接口(interface),因为数组接口(interface)是操作系统在幕后实际执行的操作

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

关于python - 为什么命令及其参数必须在 subprocess.Popen 的列表中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58440143/

相关文章:

java - 在服务器上安装 ANT(和 JAVA)

python - 将子进程输出显示到标准输出并将其重定向

python - 如何使用python卸载程序?

python - 如何将键盘输入(笔画)发送到 Linux 中的后台进程?

linux - bash中带空格的回调脚本

python - 以 sudo 身份运行 python 脚本的一部分

python - 如何在NER模型和QA模型之间做出选择?

python - 根据另一个字符串列表对字符串列表进行排序

python - numpy.linalg.lstsq 和 scipy.linalg.lstsq 有什么区别?

python - 查找已从 pcap 数据传输了多少数据