您的位置:首页 > 编程语言 > Python开发

python3模块--subprocess

2018-02-20 16:29 387 查看
subprocess模块
run函数Run函数是在python3.5之后新增,语法如下subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)(具体解释参考https://docs.python.org/3/library/subprocess.html#module-subprocess)上面的参数仅仅是基本的常用功能,我个人推荐使用run函数来使用基本功能,代替原有的call等函数当更复杂的情况下,可以使用底层的popen接口

1.call()方法:父进程等待子进程完成返回退出信息(returncode,相当于Linux exit code)Subprocess.call()=subprocess.run().returncode>>> subprocess.run('ping -c1 -W1 127.0.0.1>/dev/null', shell=True).returncode0>>> subprocess.call('ping -c1 -W1 127.0.0.1>/dev/null', shell=True)0
上面两行的代码内容是一样的,(注意shell=True的T一定是大写的)所以call是旧版的高级api,subprocess的call方法可以用于执行一个外部命令,但该方法不能返回执行的结果,只能返回执行的状态码: 成功(0) 或 错误(非0)
>>> a=subprocess.call('ping -c1 127.0.0.1',shell=True)PING 127.0.0.1 (127.0.0.1): 56 data bytes64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.054 ms
--- 127.0.0.1 ping statistics ---1 packets transmitted, 1 packets received, 0.0% packet lossround-trip min/avg/max/stddev = 0.054/0.054/0.054/0.000 ms>>> print(a)0可以看到call()目的是返回值,可以用于判断命令是否成功。
2.check_call()方法父进程等待子进程完成返回0检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性,可用try…except…来检查subprocess.check_call()=subprocess.run(…,check=True)
try:        subprocess.check_call("ls /test", shell=True)except subprocess.CalledProcessError as error:        print("check_all test:",error)结果如下/anaconda3/bin/python3 /Users/wangyizhe/Desktop/pythonIDE/python3/test.pycheck_all testls: /test: No such file or directory
Process finished with exit code 0可以看到check_call()目的是可以对错误进行处理,一般配合try…expect使用。同理上面一段代码可以用run()方法代替try:        subprocess.run("ls /test", shell=True,check=True)except subprocess.CalledProcessError as error:        print("check_all test:",error)
3.check_output() 方法call()方法启动的进程,其标准输入输出会绑定到父进程的输入和输出。调用程序无法获取命令的输出结果。但可以通过check_output()方法来捕获输出。subprocess.check_output()=run(..., check=True, stdout=PIPE).stdouta=subprocess.check_output('ls -l',shell=True,stderr=subprocess.STDOUT)print(a.decode(‘utf-8'))结果如下/anaconda3/bin/python3 /Users/wangyizhe/Desktop/pythonIDE/python3/test.pyb'crw-rw-rw-  1 root  wheel    3,   2 Feb 20 10:51 /dev/null\n'
Process finished with exit code 0同理,可以用run函数代替a=subprocess.run('ls -l /dev/null',shell=True, stdout=subprocess.PIPE).stdoutprint(a)所以可见check_output可以打印输出结果
如果不定位stdouta=subprocess.run('ls -l /dev/null',shell=True, stdout=subprocess.PIPE)print(a)结果如下/anaconda3/bin/python3 /Users/wangyizhe/Desktop/pythonIDE/python3/test.pyCompletedProcess(args='ls -l /dev/null', returncode=0, stdout=b'crw-rw-rw-  1 root  wheel    3,   2 Feb 20 10:54 /dev/null\n')
Process finished with exit code 0注意上面紫色字体,completedProcess就是run()函数的所有输出结果,包含args、returncode、stdout等
4.subprocess.popen类class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None)popen方法是一种直接处理管道与子进程通信的方法。
参数args可以是字符串或者序列类型(如:list,元组),用于指定进程的可执行文件及其参数。如果是序列类型,第一个元素通常是可执行文件的路径。我们也可以显式的使用executeable参数来指定可执行文件的路径。参数stdin, stdout, stderr分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE,文件描述符或文件对象,也可以设置为None,表示从父进程继承。如果参数shell设为true,程序将通过shell来执行。参数env是字典类型,用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
下面是popen的各种方法Popen.poll():用于检查子进程是否已经结束。设置并返回returncode属性。
Popen.wait():等待子进程结束。设置并返回returncode属性。
Popen.communicate(input=None):与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。
Popen.send_signal(signal):向子进程发送信号。
Popen.terminate():停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。
Popen.kill():杀死子进程。
Popen.pid:获取子进程的进程ID。
Popen.returncode:获取进程的返回值。如果进程还没有结束,返回None。
实际上,上面的几个函数(call()、check_call()等都是基于Popen()的封装(wrapper)。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。与上面的封装不同,Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block)
我们来看个例子例子1:
import subprocesschild=subprocess.Popen('ls -l',shell=True)parent=print('parent process’)结果/anaconda3/bin/python3 /Users/wangyizhe/Desktop/pythonIDE/python3/test.pyparent processtotal 24drwxr-xr-x  3 wangyizhe  staff   96 Feb 19 11:23 __pycache__-rw-r--r--  1 wangyizhe  staff  104 Feb 20 11:16 test.py-rw-r--r--  1 wangyizhe  staff  548 Feb 18 20:12 test_fun_time.py-rw-r--r--  1 wangyizhe  staff  628 Feb 19 23:35 testa.pydrwxr-xr-x  7 wangyizhe  staff  224 Feb 19 11:16 venvdrwxr-xr-x  6 wangyizhe  staff  192 Feb 19 17:19 venv1
Process finished with exit code 0
可以看到在子进程没有结束,代码先执行了下面的parenet父进程,然后在执行子进程,所以子进程是不会自动完成的。在对比一下import subprocesschild=subprocess.Popen('ls -l',shell=True)child.wait()parent=print('parent process’)增加了child.wait()就会先直执行完子进程在执行父进程,结果如下/anaconda3/bin/python3 /Users/wangyizhe/Desktop/pythonIDE/python3/test.pytotal 24drwxr-xr-x  3 wangyizhe  staff   96 Feb 19 11:23 __pycache__-rw-r--r--  1 wangyizhe  staff  104 Feb 20 11:19 test.py-rw-r--r--  1 wangyizhe  staff  548 Feb 18 20:12 test_fun_time.py-rw-r--r--  1 wangyizhe  staff  628 Feb 19 23:35 testa.pydrwxr-xr-x  7 wangyizhe  staff  224 Feb 19 11:16 venvdrwxr-xr-x  6 wangyizhe  staff  192 Feb 19 17:19 venv1parent process
Process finished with exit code 0
例子2:#直接打印输出结果>>> subprocess.Popen('ls -l',shell=True)<subprocess.Popen object at 0x109f3f748>>>> total 0drwxr-xr-x  5 wangyizhe  staff  160 Feb 18 10:34 python2drwxr-xr-x  9 wangyizhe  staff  288 Feb 20 11:37 python3
#将结果输入到变量中>>> a=subprocess.Popen('ls -l',shell=True,stdout=subprocess.PIPE)>>> result=a.communicate()>>> result(b'total 0\ndrwxr-xr-x  5 wangyizhe  staff  160 Feb 18 10:34 python2\ndrwxr-xr-x  9 wangyizhe  staff  288 Feb 20 11:37 python3\n', None)#打印变量的结果,注意是个元组
>>> print(result.decode('utf-8'))Traceback (most recent call last):  File "<stdin>", line 1, in <module>AttributeError: 'tuple' object has no attribute 'decode'>>> print(result[0].decode('utf-8'))total 0drwxr-xr-x  5 wangyizhe  staff  160 Feb 18 10:34 python2drwxr-xr-x  9 wangyizhe  staff  288 Feb 20 11:37 python3#将结果打印到文件中>>> file=open('/Users/wangyizhe/Desktop/file.txt','w+')>>> subprocess.Popen("ls -l",shell=True,stdout=file)<subprocess.Popen object at 0x109f3fb70>>>>  在相应目录下就保存了文件file注意:communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成
例子3:实在在终端输入python3,然后打印’wyztest’
>>> import subprocess>>> proc=subprocess.Popen(['python3'],stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE)>>> proc.stdin.write('print("wyztest")')Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: a bytes-like object is required, not 'str'>>> proc.stdin.write('print("wyztest")'.encode('utf-8'))16>>> output_val,err_val=proc.communicate()>>> output_valb'wyztest\n'>>> err_valb''>>>第一步输入python3进入交互式环境,然后通过stdin.write写入print wyztest(注意这里的编码问题,需要编码成utf-8),然后通过communicate结束子进程并复制stdout和stderr给output_val和err_val
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python