python subprocess详解

 

python subprocess详解

 

 

父进程等待子进程完成
返回退出信息(returncode,相当于Linux exit code)

  1. >>> a = subprocess.call(['df','-hT'],shell=False)
  2. 文件系统 类型 容量 已用 可用 已用% 挂载点
  3. /dev/vda3 xfs 80G 3.6G 77G 5% /
  4. devtmpfs devtmpfs 7.8G 0 7.8G 0% /dev
  5. tmpfs tmpfs 7.8G 0 7.8G 0% /dev/shm
  6. tmpfs tmpfs 7.8G 8.6M 7.8G 1% /run
  7. tmpfs tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
  8. /dev/vda6 xfs 404G 2.2G 402G 1% /data1
  9. /dev/vda2 xfs 497M 128M 370M 26% /boot
  10. tmpfs tmpfs 1.5G 0 1.5G 0% /run/user/0
  11. >>> print(a)
  12. 0 #程序返回的代码值
  13. >>> a = subprocess.call('aaaa',shell=True)
  14. /bin/sh: aaaa: 未找到命令
  15. >>>

subprocess.check_call(args, *, stdin = None, stdout = None, stderr = None, shell = False)

与call方法类似,不同在于如果命令行执行成功,check_call返回返回码0,否则抛出subprocess.CalledProcessError异常。
subprocess.CalledProcessError异常包括returncode、cmd、output等属性,其中returncode是子进程的退出码,cmd是子进程的执行命令,output为None。

  1. >>> import subprocess
  2. >>> a = subprocess.check_call('df -h',shell=True)
  3. 文件系统 容量 已用 可用 已用% 挂载点
  4. /dev/vda3 80G 3.6G 77G 5% /
  5. devtmpfs 7.8G 0 7.8G 0% /dev
  6. tmpfs 7.8G 0 7.8G 0% /dev/shm
  7. tmpfs 7.8G 8.6M 7.8G 1% /run
  8. tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
  9. /dev/vda6 404G 2.2G 402G 1% /data1
  10. /dev/vda2 497M 128M 370M 26% /boot
  11. tmpfs 1.2G 0 1.2G 0% /run/user/0
  12. >>> print(a)
  13. 0
  14. >>> a = subprocess.check_call('aaaa',shell=True)
  15. /bin/sh: aaaa: 未找到命令
  16. Traceback (most recent call last):
  17. File "<stdin>", line 1, in <module>
  18. File "/usr/local/python3/lib/python3.6/subprocess.py", line 291, in check_call
  19. raise CalledProcessError(retcode, cmd)
  20. subprocess.CalledProcessError: Command 'aaaa' returned non-zero exit status 127.
  21. >>>

用法与上面两个方法类似,区别是,如果当返回值为0时,直接返回输出结果,如果返回值不为0,直接抛出异常

  1. >>> a = subprocess.check_output(['df','-hT'],shell=False)
  2. >>> print(a)
  3. b'\xe6\x96\x87\xe4\xbb\xb6\xe7\xb3\xbb\xe7\xbb\x9f \xe7\xb1\xbb\xe5\x9e\x8b \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\n/dev/vda3 xfs 80G 3.6G 77G 5% /\ndevtmpfs devtmpfs 7.8G 0 7.8G 0% /dev\ntmpfs tmpfs 7.8G 0 7.8G 0% /dev/shm\ntmpfs tmpfs 7.8G 8.6M 7.8G 1% /run\ntmpfs tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup\n/dev/vda6 xfs 404G 2.2G 402G 1% /data1\n/dev/vda2 xfs 497M 128M 370M 26% /boot\ntmpfs tmpfs 1.5G 0 1.5G 0% /run/user/0\n'
  4. >>> print(str(a.rstrip(),'utf-8'))
  5. 文件系统 类型 容量 已用 可用 已用% 挂载点
  6. /dev/vda3 xfs 80G 3.6G 77G 5% /
  7. devtmpfs devtmpfs 7.8G 0 7.8G 0% /dev
  8. tmpfs tmpfs 7.8G 0 7.8G 0% /dev/shm
  9. tmpfs tmpfs 7.8G 8.6M 7.8G 1% /run
  10. tmpfs tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
  11. /dev/vda6 xfs 404G 2.2G 402G 1% /data1
  12. /dev/vda2 xfs 497M 128M 370M 26% /boot
  13. tmpfs tmpfs 1.5G 0 1.5G 0% /run/user/0
  14. >>>

subprocess模块定义了一个Popen类,通过它可以创建进程,并与其进行复杂的交互。

  1. class Popen(args, bufsize=0, executable=None, stdin=None,stdout=None, stderr=None, preexec_fn=None, close_fds=False,
  2. shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)

在一些复杂场景中,我们需要将一个进程的执行输出作为另一个进程的输入。在另一些场景中,我们需要先进入到某个输入环境,然后再执行一系列的指令等。这个时候我们就需要使用到suprocess的Popen()方法。该方法有以下参数

参数 作用
args 一般是一个字符串,是要执行的shell命令内容
bufsize 设置缓冲,负数表示系统默认缓冲,0表示无缓冲,正数表示自定义缓冲行数
stdin 程序的标准输入句柄,NONE表示不进行重定向,继承父进程,PIPE表示创建管道
stdout 程序的标准输出句柄,参数意义同上
stderr 程序的标准错误句柄,参数意义同上,特殊,可以设置成STDOUT,表示与标准输出一致
shell 为True时,表示将通过shell来执行
cwd 用来设置当前子进程的目录
env 用于指定子进程的环境变量。如果env=None,则默认从父进程继承环境变量
universal_newlines 不同系统的的换行符不同,当该参数设定为true时,则表示使用\n作为换行符。
  • 1、Popen.poll():用于检查子进程是否已经结束。设置并返回returncode属性。
  • 2、Popen.wait():等待子进程结束。设置并返回returncode属性。
  • 3、Popen.communicate(input=None):与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。
  • 4、Popen.send_signal(signal):向子进程发送信号。
  • 5、Popen.terminate():停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。
  • 6、Popen.kill():杀死子进程。
  • 7、Popen.stdin:如果在创建Popen对象是,参数stdin被设置为PIPE,Popen.stdin将返回一个文件对象用于策子进程发送指令。否则返回None。
  • 8、Popen.stdout:如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回None。
  • 9、Popen.stderr:如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回None。
  • 10、Popen.pid:获取子进程的进程ID。
  • 11、Popen.returncode:获取进程的返回值。如果进程还没有结束,返回None。
  • 12、subprocess.call(*popenargs, **kwargs):运行命令。该函数将一直等待到子进程运行结束,并返回进程的returncode。文章一开始的例子就演示了call函数。如果子进程不需要进行交互,就可以使用该函数来创建。
  • 13、subprocess.check_call(popenargs, **kwargs):与subprocess.call(popenargs, **kwargs)功能一样,只是如果子进程返回的returncode不为0的话,将触发CalledProcessError异常。在异常对象中,包括进程的returncode信息
  1. >>> import subprocess
  2. >>> subprocess.Popen('/apps/apache-tomcat-8.5.29/bin/startup.sh',shell=True)
  3. <subprocess.Popen object at 0x7f3579b2dfd0>
  4. >>> Using CATALINA_BASE: /apps/apache-tomcat-8.5.29
  5. Using CATALINA_HOME: /apps/apache-tomcat-8.5.29
  6. Using CATALINA_TMPDIR: /apps/apache-tomcat-8.5.29/temp
  7. Using JRE_HOME: /usr/java/jdk1.8.0_111/
  8. Using CLASSPATH: /apps/apache-tomcat-8.5.29/bin/bootstrap.jar:/apps/apache-tomcat-8.5.29/bin/tomcat-juli.jar
  9. Tomcat started.
  10. >>> popen = subprocess.Popen('tail -f /apps/apache-tomcat-8.5.29/logs/catalina.out',shell=True)
  11. >>> at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1086)
  12. at org.apache.tomcat.util.net.AbstractJsseEndpoint.init(AbstractJsseEndpoint.java:268)
  13. at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:581)
  14. at org.apache.catalina.connector.Connector.initInternal(Connector.java:993)
  15. ... 13 more
  16. 19-Nov-2019 17:05:05.020 信息 [main] org.apache.catalina.startup.Catalina.load Initialization processed in 650 ms
  17. 19-Nov-2019 17:05:05.045 信息 [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
  18. 19-Nov-2019 17:05:05.045 信息 [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.29
  19. 19-Nov-2019 17:05:05.061 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/apps/apache-tomcat-8.5.29/webapps/ROOT]
  20. KeyboardInterrupt
  21. >>> popen.terminate()
  22. >>>

在shell=True这个参数,不写的时候默认是False,shell默认为/bin/sh。如果 args是一个字符串,则该字符串指定要通过shell执行的命令。
当需要设置shell=True时(当False时,arges是列表,第一个参数是shell命令,后面的都是参数’,’ 隔开),须把args设为string,空格隔开,如下

  1. >>> a = subprocess.Popen(['tail','-f', '/apps/apache-tomcat-8.5.29/logs/catalina.out'])
  2. >>> a = subprocess.Popen('tail -f /apps/apache-tomcat-8.5.29/logs/catalina.out',shell=True)
版权声明:本文为BioMarkerInfo原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/xiaojikuaipao/p/16546519.html