使用 subprocess 执行 cmd
# 使用 subprocess 执行 cmd
# 关于 subprocess
subprocess 这个模块可以用来产生子进程,并连接到子进程的标准输入/输出/错误中去,还可以得到子进程的返回值。
它是一个标准库,无需另外安装。
subprocess 意在替代其他几个老的模块或者函数,将它们的功能集中到一起:
- os.system
- os.spawn*
- os.popen* –废弃
- popen2.* –废弃
- commands.* –废弃,3.x中被移除
# subprocess.Popen()
Popen 类用于创建和管理进程,子程序将在新进程中被执行完成。在 UNIX/Linux 中执行子程序,该类会使用 os.execvp()
函数。而在 Windows 中执行子程序,该类将使用 CreateProcess()
函数。
首先看一下 subprocess.Popen()
的常用参数:
class subprocess.Popen(args, bufsize=0, executable=None, stdin=None,
stdout=None, close_fds=False, shell=False, universal_newlines=False,
stderr=None, preexec_fn=None, cwd=None, env=None, startupinfo=None, creationflags=0)
1
2
3
2
3
- args:它可以是一系列程序参数或单个字符串。如果 args 是一个序列,则 args 中的第一项将作为程序被执行。如果 args 是一个字符串,则会将 args 作为序列传递。
- bufsize:如果 bufsize 为 0(默认值是 0),则表示无缓冲。如果 bufsize 为 1,则表示行缓冲。如果 bufsize 是任何其他正值,则使用给定大小的缓冲区。如果 bufsize 是任何其他负值,则表示完全缓冲。
- executable:指定替换程序。
- stdin、stdout 和 stderr:这些参数分别定义标准输入、标准输出和标准错误。
- close_fds:在 Linux 中,如果 close_fds 为 True,则程序在执行子进程之前将关闭除 0、1 和 2 之外的所有文件描述符。在 Windows 中,如果 close_fds 为 True,则子进程将不继承句柄。
- shell:它表示是否使用 Shell 执行程序,默认为 False。
- 如果 shell 为 True,则会将 args 作为字符串传递。在 Linux 中,如果 shell 为 True,则 Shell 程序默认为
/bin/sh
。如果 args 是一个字符串,则该字符串指定要通过 Shell 执行的命令。 - 如果 shell 为 False,则需要将 args 作为数组传递,并将数组的第一个元素作为命令,剩下的全部作为该命令的参数。
- 如果 shell 为 True,则会将 args 作为字符串传递。在 Linux 中,如果 shell 为 True,则 Shell 程序默认为
- preexec_fn:设置可调用对象,将在执行子进程之前调用。
- env:如果值不是 None,则映射将为新进程定义环境变量。
- universal_newlines:如果值为 True,则 stdout 和 stderr 将以自动换行模式打开文本文件。
下面是几个示例程序 (opens new window)。
# 执行命令,不等待子进程
import subprocess
def exec_without_block():
# 或者:child = subprocess.Popen(['ping', '-c', '4', 'www.baidu.com'])
child = subprocess.Popen('ping -c 4 www.baidu.com', shell=True)
print(child)
print('hello world')
1
2
3
4
5
6
7
2
3
4
5
6
7
从执行结果可以看到 Python 并没有等到 child 子进程执行的 Popen 操作完成就执行了 print 操作。
# 执行命令,添加子进程等待
为了让主程序等待子进程完成后再继续往下执行,我们必须调用 Popen 对象的 wait()
方法,这样父进程才会等待(也就是阻塞 block)。
import subprocess
def exec_with_block():
child = subprocess.Popen('ping -c 4 www.baidu.com', shell=True)
child.wait()
print(child)
print('hello world')
1
2
3
4
5
6
7
2
3
4
5
6
7
# 执行命令,获取返回结果
我们可以在 Popen() 建立子进程的时候改变标准输入、标准输出和标准错误,从而获取执行结果,如下例子。
import subprocess
# 获取命令执行结果
def get_exec_result():
child = subprocess.Popen('cat /etc/issue',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
child.wait()
result = child.stdout.read()
if not result:
err = child.stderr.read()
print(sys.stderr, 'ERROR: %s' % err)
else:
print(result)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 参考资料
(完)