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'\xe6\x96\x87\xe4\xbb\xb6\xe7\xb3\xbb\xe7\xbb\x9f \xe5\xae\xb9\xe9\x87\x8f \xe5\xb7\xb2\xe7\x94\xa8 \xe5\x8f\xaf\xe7\x94\xa8 \xe5\xb7\xb2\xe7\x94\xa8% \xe6\x8c\x82\xe8\xbd\xbd\xe7\x82\xb9\nudev 468M 0 468M 0% /dev\ntmpfs 98M 7.4M 91M 8% /run\n/dev/sda1 39G 5.0G 32G 14% /\ntmpfs 488M 216K 488M 1% /dev/shm\ntmpfs 5.0M 4.0K 5.0M 1% /run/lock\ntmpfs 488M 0 488M 0% /sys/fs/cgroup\ntmpfs 98M 84K 98M 1% /run/user/1000\n' >>> a.stdout.decode() '文件系统 容量 已用 可用 已用% 挂载点\nudev 468M 0 468M 0% /dev\ntmpfs 98M 7.4M 91M 8% /run\n/dev/sda1 39G 5.0G 32G 14% /\ntmpfs 488M 216K 488M 1% /dev/shm\ntmpfs 5.0M 4.0K 5.0M 1% /run/lock\ntmpfs 488M 0 488M 0% /sys/fs/cgroup\ntmpfs 98M 84K 98M 1% /run/user/1000\n' >>> a.stderr # 如果命令执行成功,读取的错误就为空 b'' >>> a = subprocess.run(['df','-asdh'],stdout=subprocess.PIPE,stderr=subprocess.PIPE) >>> a.stdout.decode() # 如果命令执行错误,读出来的执行结果就为空 '' >>> a.stderr # 如果命令执行错误,就能读出错误的内容 b"df\xef\xbc\x9a\xe6\x97\xa0\xe6\x95\x88\xe9\x80\x89\xe9\xa1\xb9 -- s\nTry 'df --help' for more information.\n" >>> a.stderr.decode() "df:无效选项 -- s\nTry 'df --help' for more information.\n"
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\nTry 'df --help' for more information.\n" >>> 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% /\n', 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() '文件系统 容量 已用 可用 已用% 挂载点\nudev 468M 0 468M 0% /dev\ntmpfs 98M 7.4M 91M 8% /run\n/dev/sda1 39G 5.0G 32G 14% /\ntmpfs 488M 216K 488M 1% /dev/shm\ntmpfs 5.0M 4.0K 5.0M 1% /run/lock\ntmpfs 488M 0 488M 0% /sys/fs/cgroup\ntmpfs 98M 84K 98M 1% /run/user/1000\n' >>> a = subprocess.check_output(['df','-h']).decode() >>> a '文件系统 容量 已用 可用 已用% 挂载点\nudev 468M 0 468M 0% /dev\ntmpfs 98M 7.4M 91M 8% /run\n/dev/sda1 39G 5.0G 32G 14% /\ntmpfs 488M 216K 488M 1% /dev/shm\ntmpfs 5.0M 4.0K 5.0M 1% /run/lock\ntmpfs 488M 0 488M 0% /sys/fs/cgroup\ntmpfs 98M 84K 98M 1% /run/user/1000\n'
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\n' >>> 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"a\x7fa.cco\t'ch01ar')\n", 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\nsch01ar\n'
cwd:用于设置子进程的当前目录
>>> a = subprocess.Popen('echo $PWD',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) >>> a.stdout.read() b'/home/sch01ar\n' >>> a = subprocess.Popen('echo $PWD',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd='/home/sch01ar/Desktop/') >>> a.stdout.read() b'/home/sch01ar/Desktop\n'
shell的作用跟subprocess.run()方法中的shell作用一样
env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承