Python subprocess模块详解:从基础调用到复杂交互

Ruby
Ruby
发布时间:2026-10-13 | 7人浏览过
原创

本文详解Python中subprocess模块的用法,涵盖call、check_call、check_output及Popen等核心方法。通过对比废弃模块,展示如何安全执行系统命令、处理状态码及捕获输出,并深入解析Popen参数与交互式进程控制技巧。

在Python中,执行Shell命令存在多个相关模块和函数可选:

  • os.system
  • os.spawn
  • os.popen(已废弃)
  • popen(已废弃)
  • commands(已废弃,在Python 3.x版本中已被移除)

上述执行Shell命令的模块和函数功能,目前均已在subprocess模块中实现,且该模块提供了更为丰富和强大的功能支持。

subprocess

call

用于执行命令,并返回命令执行的状态码。

>>> import subprocess
>>> ret = subprocess.call(["ls", "-l"], shell=False)
total 4684
-rw-r--r-- 1 root root   454 May 5 12:20 aa.py
-rw-r--r-- 1 root root    0 May 8 16:51 aa.txt
-rw-r--r-- 1 root root 4783286 Apr 11 16:39 DockerToolbox.exe
-rw-r--r-- 1 root root   422 May 5 12:20 ip_info.txt
-rw-r--r-- 1 root root   718 Apr 19 10:52 my.cnf
>>> ret = subprocess.call("ls -l", shell=True)
total 4684
-rw-r--r-- 1 root root   454 May 5 12:20 aa.py
-rw-r--r-- 1 root root    0 May 8 16:51 aa.txt
-rw-r--r-- 1 root root 4783286 Apr 11 16:39 DockerToolbox.exe
-rw-r--r-- 1 root root   422 May 5 12:20 ip_info.txt
-rw-r--r-- 1 root root   718 Apr 19 10:52 my.cnf
>>> print(ret)
0

check_call

执行命令,若执行状态码为0则返回0;若状态码非0,则抛出异常。

>>> subprocess.check_call(["ls", "-l"])
total 4684
-rw-r--r-- 1 root root   454 May 5 12:20 aa.py
-rw-r--r-- 1 root root    0 May 8 16:51 aa.txt
-rw-r--r-- 1 root root 4783286 Apr 11 16:39 DockerToolbox.exe
-rw-r--r-- 1 root root   422 May 5 12:20 ip_info.txt
-rw-r--r-- 1 root root   718 Apr 19 10:52 my.cnf
0
>>> subprocess.check_call("exit 1", shell=True)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "/usr/local/python3.5/lib/python3.5/subprocess.py", line 581, in check_call
  raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

check_output

执行命令,若状态码为0则返回执行结果;若状态码非0,则抛出异常。

>>> subprocess.check_output(["echo", "Hello World!"])
b'Hello World!\n'
>>> subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "/usr/local/python3.5/lib/python3.5/subprocess.py", line 626, in check_output
  **kwargs).stdout
 File "/usr/local/python3.5/lib/python3.5/subprocess.py", line 708, in run
  output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

subprocess.Popen(...)

用于执行更为复杂的系统命令。

参数说明如下:

args:Shell命令,可以是字符串形式,也可以是序列类型(如list或tuple)。

bufsize:指定缓冲策略。0表示无缓冲,1表示行缓冲,其他正整数表示缓冲区大小,负值表示使用系统默认缓冲。

stdin、stdout、stderr:分别表示子进程的标准输入、标准输出和标准错误句柄。

preexec_fn:仅在Unix平台下有效,用于指定一个可调用对象(callable object),该对象将在子进程运行之前被调用。

close_fds:在Windows平台下,若将close_fds设置为True,则新创建的子进程将不会继承父进程的输入、输出及错误管道。

因此,不能将close_fds设置为True的同时,又重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。

shell:同上,控制是否通过Shell执行命令。

cwd:用于设置子进程的当前工作目录。

env:用于指定子进程的环境变量。若env为None,子进程的环境变量将从父进程中继承。

universal_newlines:不同操作系统的换行符存在差异,设置为True时统一使用'n'作为换行符。

startupinfo与creationflags:仅在Windows平台下有效。

这两个参数将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,例如主窗口的外观、进程的优先级等。

执行普通命令的示例如下:

>>> import subprocess
>>> ret1 = subprocess.Popen(["mkdir","t1"])
>>> ret2 = subprocess.Popen("mkdir t2", shell=True)
>>> print(ret1)
<subprocess.Popen object at 0x7f4d7609dd30>
>>> print(ret2)
<subprocess.Popen object at 0x7f4d7609dc18>

终端中输入的命令主要分为两种类型:

  • 输入命令后直接返回输出结果,例如:ifconfig。
  • 输入命令后进入某个交互环境,需依赖后续输入进行操作,例如:python。
>>> import subprocess
>>> obj = subprocess.Popen("mkdir t3", shell=True, cwd='/tmp/',)
>>> import subprocess
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
>>> obj.stdin.write("print(1)\n")
9
>>> obj.stdin.write("print(2)")
8
>>> obj.stdin.close()
>>> cmd_out = obj.stdout.read()
>>> obj.stdout.close()
>>> cmd_error = obj.stderr.read()
>>> obj.stderr.close()
>>> print(cmd_out)
1
2
>>> print(cmd_error)
>>> import subprocess
>>> 
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
>>> obj.stdin.write("print(1)\n")
9
>>> obj.stdin.write("print(2)")
8
>>> 
>>> out_error_list = obj.communicate()
>>> print(out_error_list)
('1\n2\n', '')
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
>>> out_error_list = obj.communicate('print("hello")')
>>> print(out_error_list)
('hello\n', '')

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表