Python模块-subprocess模块

Run()方法

>>> a = subprocess.run(['df','-h'])
文件系统        容量  已用  可用 已用% 挂载点
udev            468M     0  468M    0% /dev
tmpfs            98M  7.4M   91M    8% /run
/dev/sda1        39G  5.0G   32G   14% /
tmpfs           488M  216K  488M    1% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
tmpfs           488M     0  488M    0% /sys/fs/cgroup
tmpfs            98M   84K   98M    1% /run/user/1000
>>> a
CompletedProcess(args=['df', '-h'], returncode=0)
>>> a.returncode  # 获取命令执行结果的状态码
0
>>> a.args  # 获取命令参数列表
['df', '-h']

 直接把命令按照列表传入

 如果想要读取命令执行的结果和错误,需要通过管道

>>> a = subprocess.run(['df','-h'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> a.stdout  # 如果命令执行成功就能读出执行结果
b'xe6x96x87xe4xbbxb6xe7xb3xbbxe7xbbx9f        xe5xaexb9xe9x87x8f  xe5xb7xb2xe7x94xa8  xe5x8fxafxe7x94xa8 xe5xb7xb2xe7x94xa8% xe6x8cx82xe8xbdxbdxe7x82xb9
udev            468M     0  468M    0% /dev
tmpfs            98M  7.4M   91M    8% /run
/dev/sda1        39G  5.0G   32G   14% /
tmpfs           488M  216K  488M    1% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
tmpfs           488M     0  488M    0% /sys/fs/cgroup
tmpfs            98M   84K   98M    1% /run/user/1000
'
>>> a.stdout.decode()
'文件系统        容量  已用  可用 已用% 挂载点
udev            468M     0  468M    0% /dev
tmpfs            98M  7.4M   91M    8% /run
/dev/sda1        39G  5.0G   32G   14% /
tmpfs           488M  216K  488M    1% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
tmpfs           488M     0  488M    0% /sys/fs/cgroup
tmpfs            98M   84K   98M    1% /run/user/1000
'
>>> a.stderr  # 如果命令执行成功,读取的错误就为空
b''
>>> a = subprocess.run(['df','-asdh'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> a.stdout.decode()  # 如果命令执行错误,读出来的执行结果就为空
''
>>> a.stderr  # 如果命令执行错误,就能读出错误的内容
b"dfxefxbcx9axe6x97xa0xe6x95x88xe9x80x89xe9xa1xb9 -- s
Try 'df --help' for more information.
"
>>> a.stderr.decode()
"df:无效选项 -- s
Try 'df --help' for more information.
"

 stdout=subprocess.PIPE为命令执行成功返回的内容

 stderr=subprocess.PIPE为命令执行错误返回的错误内容

 因为执行一条命令就会打开一个进程,进程间数据不能通信,所以操作系统对stdout、stderr的结果进行读取,再传给程序

 subprocess.run()方法执行命令时,如果命令是错的,程序不会报错而继续运行,如果要命令错的时候程序报错停止运行的话,可以加个check参数

 check参数设置为True的时候就会检查命令是否是错的

>>> a = subprocess.run(['df','-asdh'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> a.stderr.decode()
"df:无效选项 -- s
Try 'df --help' for more information.
"
>>> a = subprocess.run(['df','-asdh'],stdout=subprocess.PIPE,stderr=subprocess.PIPE,check=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/subprocess.py", line 708, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['df', '-asdh']' returned non-zero exit status 1

 执行带有管道符的命令

>>> a = subprocess.run('df -h |grep sda1',stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
>>> a
CompletedProcess(args='df -h |grep sda1', returncode=0, stdout=b'/dev/sda1        39G  5.0G   32G   14% /
', stderr=b'')

Call()方法

 执行命令,返回命令执行状态

>>> retcode = subprocess.call(['df', '-h'])
文件系统        容量  已用  可用 已用% 挂载点
udev            468M     0  468M    0% /dev
tmpfs            98M  7.4M   91M    8% /run
/dev/sda1        39G  5.0G   32G   14% /
tmpfs           488M  216K  488M    1% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
tmpfs           488M     0  488M    0% /sys/fs/cgroup
tmpfs            98M   84K   98M    1% /run/user/1000
>>> retcode
0

 执行命令,如果命令执行状态为0,就正常返回,否则抛异常

>>> subprocess.check_call(['df', '-h'])
文件系统        容量  已用  可用 已用% 挂载点
udev            468M     0  468M    0% /dev
tmpfs            98M  7.4M   91M    8% /run
/dev/sda1        39G  5.0G   32G   14% /
tmpfs           488M  216K  488M    1% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
tmpfs           488M     0  488M    0% /sys/fs/cgroup
tmpfs            98M   84K   98M    1% /run/user/1000
0
>>> subprocess.check_call(['df', '-ash'])
df:无效选项 -- s
Try 'df --help' for more information.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['df', '-ash']' returned non-zero exit status 1

 接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果

>>> subprocess.getstatusoutput('whoami')
(0, 'sch01ar')

 接收字符串格式命令,并返回结果

>>> subprocess.getoutput('whoami')
'sch01ar'

 执行命令,并返回结果

>>> subprocess.check_output(['df','-h']).decode()
'文件系统        容量  已用  可用 已用% 挂载点
udev            468M     0  468M    0% /dev
tmpfs            98M  7.4M   91M    8% /run
/dev/sda1        39G  5.0G   32G   14% /
tmpfs           488M  216K  488M    1% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
tmpfs           488M     0  488M    0% /sys/fs/cgroup
tmpfs            98M   84K   98M    1% /run/user/1000
'
>>> a = subprocess.check_output(['df','-h']).decode()
>>> a
'文件系统        容量  已用  可用 已用% 挂载点
udev            468M     0  468M    0% /dev
tmpfs            98M  7.4M   91M    8% /run
/dev/sda1        39G  5.0G   32G   14% /
tmpfs           488M  216K  488M    1% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
tmpfs           488M     0  488M    0% /sys/fs/cgroup
tmpfs            98M   84K   98M    1% /run/user/1000
'

Popen()方法

popen()方法执行命令的进程和主程序的进程为并行

>>> subprocess.run(['sleep','10'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
CompletedProcess(args=['sleep', '10'], returncode=0, stdout=b'', stderr=b'')
>>> subprocess.Popen(['sleep','10'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
<subprocess.Popen object at 0x7f7fe17adda0>

 subprocess.run()睡眠10秒之后才返回,subprocess.Popen()直接返回

>>> a = subprocess.Popen(['sleep','10'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> a.wait()
0

 wait()会等待进程结束

>>> a = subprocess.Popen(['whoami'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> a.stdout.read()  # 读取命令执行成功的结果
b'sch01ar
'
>>> a.stderr.read()  # 读取命令执行错误的结果
b''
>>> a.poll()  #检查子进程是否已终止,返回返回值
0
>>> a.args  # 返回命令参数
['whoami']
>>> a.pid  # 返回当前命令的进程号
24999
>>> a.returncode  # 返回返回值
0

 terminate():给系统发信号,终止所启动的进程,不一定会终止

 kill():杀死所启动的进程

 communicate():与启动的进程交互,发送数据到stdin,并从stdout接收输出,然后等待任务结束

>>> a = subprocess.Popen(['python3','test.py'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> a.communicate('sch01ar')
(b"ax7fa.cco	'ch01ar')
", b'')

 communicate()只能与启动的进程交互一次

 send_signal():发送系统信号

>>> a = subprocess.Popen(['sleep','30'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> a.send_signal(signal.SIGKILL)

 preexec_fn:只在Unix平台下有效,用于指定一个函数,它将在子进程运行之前被调用

>>> def test():
...    print('This is a test')
... 
>>> a = subprocess.Popen(['whoami'],stdout=subprocess.PIPE,stderr=subprocess.PIPE,preexec_fn=test)
>>> a.stdout.read()
b'This is a test
sch01ar
'

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

>>> a = subprocess.Popen('echo $PWD',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> a.stdout.read()
b'/home/sch01ar
'
>>> a = subprocess.Popen('echo $PWD',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/home/sch01ar/Desktop/')
>>> a.stdout.read()
b'/home/sch01ar/Desktop
'

 shell的作用跟subprocess.run()方法中的shell作用一样

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

原文地址:https://www.cnblogs.com/sch01ar/p/8491088.html