python subprocess詳解


python subprocess詳解

簡介:

運行python的時候,我們都是在創建並運行一個進程。像Linux進程那樣,一個進程可以fork一個子進程,並讓這個子進程exec另外一個程序。在Python中,我們通過標准庫中的subprocess包來fork一個子進程,並運行一個外部的程序。
subprocess包中定義有數個創建子進程的函數,這些函數分別以不同的方式創建子進程,所以我們可以根據需要來從中選取一個使用。另外subprocess還提供了一些管理標准流(standard stream)和管道(pipe)的工具,從而在進程間使用文本通信。

subprocess.call()

父進程等待子進程完成
返回退出信息(returncode,相當於Linux exit code)

示例:

>>> a = subprocess.call(['df','-hT'],shell=False)
文件系統       類型      容量  已用  可用 已用% 掛載點
/dev/vda3      xfs        80G  3.6G   77G    5% /
devtmpfs       devtmpfs  7.8G     0  7.8G    0% /dev
tmpfs          tmpfs     7.8G     0  7.8G    0% /dev/shm
tmpfs          tmpfs     7.8G  8.6M  7.8G    1% /run
tmpfs          tmpfs     7.8G     0  7.8G    0% /sys/fs/cgroup
/dev/vda6      xfs       404G  2.2G  402G    1% /data1
/dev/vda2      xfs       497M  128M  370M   26% /boot
tmpfs          tmpfs     1.5G     0  1.5G    0% /run/user/0
>>> print(a)
0    #程序返回的代碼值
>>> a = subprocess.call('aaaa',shell=True)
/bin/sh: aaaa: 未找到命令
>>> 

subprocess.check_call()

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。

示例:

>>> import subprocess
>>> a = subprocess.check_call('df -h',shell=True)
文件系統        容量  已用  可用 已用% 掛載點
/dev/vda3        80G  3.6G   77G    5% /
devtmpfs        7.8G     0  7.8G    0% /dev
tmpfs           7.8G     0  7.8G    0% /dev/shm
tmpfs           7.8G  8.6M  7.8G    1% /run
tmpfs           7.8G     0  7.8G    0% /sys/fs/cgroup
/dev/vda6       404G  2.2G  402G    1% /data1
/dev/vda2       497M  128M  370M   26% /boot
tmpfs           1.2G     0  1.2G    0% /run/user/0
>>> print(a)
0
>>> a = subprocess.check_call('aaaa',shell=True)
/bin/sh: aaaa: 未找到命令
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/python3/lib/python3.6/subprocess.py", line 291, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'aaaa' returned non-zero exit status 127.
>>> 

subprocess.check_output():

用法與上面兩個方法類似,區別是,如果當返回值為0時,直接返回輸出結果,如果返回值不為0,直接拋出異常

示例:

>>> a = subprocess.check_output(['df','-hT'],shell=False)
>>> print(a)
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'
>>> print(str(a.rstrip(),'utf-8'))
文件系統       類型      容量  已用  可用 已用% 掛載點
/dev/vda3      xfs        80G  3.6G   77G    5% /
devtmpfs       devtmpfs  7.8G     0  7.8G    0% /dev
tmpfs          tmpfs     7.8G     0  7.8G    0% /dev/shm
tmpfs          tmpfs     7.8G  8.6M  7.8G    1% /run
tmpfs          tmpfs     7.8G     0  7.8G    0% /sys/fs/cgroup
/dev/vda6      xfs       404G  2.2G  402G    1% /data1
/dev/vda2      xfs       497M  128M  370M   26% /boot
tmpfs          tmpfs     1.5G     0  1.5G    0% /run/user/0
>>> 

subprocess.Popen():

subprocess模塊定義了一個Popen類,通過它可以創建進程,並與其進行復雜的交互。

class Popen(args, bufsize=0, executable=None, stdin=None,stdout=None, stderr=None, preexec_fn=None, close_fds=False, 
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作為換行符。

Popen方法:

  • 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信息

示例:

>>> import subprocess
>>> subprocess.Popen('/apps/apache-tomcat-8.5.29/bin/startup.sh',shell=True)
<subprocess.Popen object at 0x7f3579b2dfd0>
>>> Using CATALINA_BASE:   /apps/apache-tomcat-8.5.29
Using CATALINA_HOME:   /apps/apache-tomcat-8.5.29
Using CATALINA_TMPDIR: /apps/apache-tomcat-8.5.29/temp
Using JRE_HOME:        /usr/java/jdk1.8.0_111/
Using CLASSPATH:       /apps/apache-tomcat-8.5.29/bin/bootstrap.jar:/apps/apache-tomcat-8.5.29/bin/tomcat-juli.jar
Tomcat started.

>>> popen = subprocess.Popen('tail -f /apps/apache-tomcat-8.5.29/logs/catalina.out',shell=True)
>>> 	at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1086)
	at org.apache.tomcat.util.net.AbstractJsseEndpoint.init(AbstractJsseEndpoint.java:268)
	at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:581)
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:993)
	... 13 more

19-Nov-2019 17:05:05.020 信息 [main] org.apache.catalina.startup.Catalina.load Initialization processed in 650 ms
19-Nov-2019 17:05:05.045 信息 [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
19-Nov-2019 17:05:05.045 信息 [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.29
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]

KeyboardInterrupt
>>> popen.terminate()
>>> 

注意!

在shell=True這個參數,不寫的時候默認是False,shell默認為/bin/sh。如果 args是一個字符串,則該字符串指定要通過shell執行的命令。
當需要設置shell=True時(當False時,arges是列表,第一個參數是shell命令,后面的都是參數',' 隔開),須把args設為string,空格隔開,如下

>>> a = subprocess.Popen(['tail','-f', '/apps/apache-tomcat-8.5.29/logs/catalina.out'])
>>> a = subprocess.Popen('tail -f /apps/apache-tomcat-8.5.29/logs/catalina.out',shell=True)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM