python之subprocess模組

來源:互聯網
上載者:User

標籤:不同   ret   object   意思   移除   env   cal   指定   序列   

Python中可以執行shell命令的相關模組和函數有:

  • os.system
  • os.spawn*
  • os.popen*          --廢棄
  • popen2.*           --廢棄
  • commands.*      --廢棄,3.x中被移除
import commandsresult = commands.getoutput(‘cmd‘)result = commands.getstatus(‘cmd‘)result = commands.getstatusoutput(‘cmd‘)

  隨著Python版本的更新,過多的模組引起代碼的複雜與冗餘,因此Python新引入了一個模組subprocess,將以上幾個模組中的功能集中到它當中,以後我們只需import這一個即可。

subprocess的目的就是啟動一個新的進程並且與之通訊。

1. call

父進程等待子進程執行命令,返回子進程執行命令的狀態代碼,如果出現錯誤,不進行報錯

【這裡說的返回執行命令的狀態代碼的意思是:如果我們通過一個變數 res = subprocess.call([‘dir‘,shell=True]) 擷取的執行結果,我們能擷取到的是子進程執行命令執行結果的狀態代碼,即res=0/1 執行成功或者不成功,並不代表說看不到執行結果,在Python的console介面中我們是能夠看到命令結果的,只是擷取不到。想擷取執行的返回結果,請看check_output。】

【不進行報錯解釋:如果我們執行的命令在執行時,作業系統不識別,系統會返回一個錯誤,如:abc命令不存在,這個結果會在console介面中顯示出來,但是我們的Python解譯器不會提示任何資訊,如果想讓Python解譯器也進行報錯,請看check_call】

#!/usr/bin/env python# -*- coding:utf-8 -*-import subprocessprint "################## subprocess.call ###############"print u"call方法調用系統命令進行執行,如果出錯不報錯"subprocess.call([‘dir‘],shell=True)
註:shell預設為False,在Linux下,shell=False時, Popen調用os.execvp()執行args指定的程式;shell=True時,如果args是字串,Popen直接調用系統的Shell來執行args指定的程式,如果args是一個序列,則args的第一項是定義程式命令字串,其它項是調用系統Shell時的附加參數。
  在Windows下,不論shell的值如何,Popen調用CreateProcess()執行args指定的外部程式。如果args是一個序列,則先用list2cmdline()轉化為字串,但需要注意的是,並不是MS Windows下所有的程式都可以用list2cmdline來轉化為命令列字串。在windows下,呼叫指令碼時要寫上shell=True。

返回結果:

###### subprocess.call #######call方法調用系統命令進行執行,如果出錯不報錯 D:\Program\Python 的目錄2016/01/27  11:51             1,069 subprocessDemo.py               1 個檔案          1,228 位元組

2. check_call

父進程等待子進程執行命令,返回執行命令的狀態代碼,如果出現錯誤,進行報錯【如果returncode不為0,則舉出錯誤subprocess.CalledProcessError,該對象包含有returncode屬性,可用try…except…來檢查】

#!/usr/bin/env python# -*- coding:utf-8 -*-import subprocessprint "2. ################## subprocess.check_call ##########"print u"check_call與call命令相同,區別是如果出錯會報錯"subprocess.check_call([‘dir‘],shell=True)subprocess.check_call([‘abc‘],shell=True)print u"call方法與check_call方法都知識執行並列印命令到輸出終端,但是擷取不到,如果想擷取到結果使用check_output"

返回結果

2. ################## subprocess.check_call ##########check_call與call命令相同,區別是如果出錯會報錯 磁碟機 D 中的卷沒有標籤。 卷的序號是 C6A1-5AD3 D:\Program\Python 的目錄2016/01/27  13:05    <DIR>          .2016/01/27  13:05    <DIR>          ..2016/01/27  10:44    <DIR>          .idea2016/01/27  11:23               159 log_analyse.py2016/01/27  13:05             1,329 subprocessDemo.py               2 個檔案          1,488 位元組               3 個目錄 26,335,281,152 可用位元組‘abc‘ 不是內部或外部命令,也不是可啟動並執行程式或批次檔。                    這裡是系統執行命令返回的系統報錯Traceback (most recent call last):                              這裡是Python解譯器返回的報錯  File "D:/Program/Python/subprocessDemo.py", line 19, in <module>    subprocess.check_call([‘abc‘],shell=True)  File "C:\Python27\lib\subprocess.py", line 540, in check_call    raise CalledProcessError(retcode, cmd)subprocess.CalledProcessError: Command ‘[‘abc‘]‘ returned non-zero exit status 1

3. check_output

父進程等待子進程執行命令,返回子進程向標準輸出發送輸出運行結果,檢查退出資訊,如果returncode不為0,則舉出錯誤subprocess.CalledProcessError,該對象包含有returncode屬性和output屬性,output屬性為標準輸出的輸出結果,可用try…except…來檢查。

 

#!/usr/bin/env python# -*- coding:utf-8 -*-import subprocessprint "3. ################## subprocess.check_output ##############"res1 = subprocess.call([‘dir‘],shell=True)res2 = subprocess.check_call([‘dir‘],shell=True)res3 = subprocess.check_output([‘dir‘],shell=True)print u"call結果:",res1print u"check_call結果:",res2print u"check_output結果:\n",res3

 

返回結果:

3. ################## subprocess.output ############## 磁碟機 D 中的卷沒有標籤。 卷的序號是 C6A1-5AD3 D:\Program\Python 的目錄2016/01/27  13:14    <DIR>          .2016/01/27  13:14    <DIR>          ..2016/01/27  10:44    <DIR>          .idea2016/01/27  11:23               159 log_analyse.py2016/01/27  13:14             1,324 subprocessDemo.py               2 個檔案          1,483 位元組               3 個目錄 26,334,232,576 可用位元組 磁碟機 D 中的卷沒有標籤。 卷的序號是 C6A1-5AD3 D:\Program\Python 的目錄2016/01/27  13:14    <DIR>          .2016/01/27  13:14    <DIR>          ..2016/01/27  10:44    <DIR>          .idea2016/01/27  11:23               159 log_analyse.py2016/01/27  13:14             1,324 subprocessDemo.py               2 個檔案          1,483 位元組               3 個目錄 26,334,232,576 可用位元組call結果: 0check_call結果: 0check_output結果: 磁碟機 D 中的卷沒有標籤。 卷的序號是 C6A1-5AD3 D:\Program\Python 的目錄2016/01/27  13:14    <DIR>          .2016/01/27  13:14    <DIR>          ..2016/01/27  10:44    <DIR>          .idea2016/01/27  11:23               159 log_analyse.py2016/01/27  13:14             1,324 subprocessDemo.py               2 個檔案          1,483 位元組               3 個目錄 26,334,232,576 可用位元組

可見,call/check_call  傳回值均是命令的執行狀態代碼,而check_output傳回值是命令的執行結果。

如果在執行相關命令時,命令後帶有參數,將程式名(即命令)和所帶的參數一起放在一個列表中傳遞給相關犯法即可,例如:

>>> import subprocess>>> retcode = subprocess.call(["ls", "-l"])>>> print retcode0

 

4. Popen

  實際上,subprocess模組中只定義了一個類: Popen。上面的幾個函數都是基於Popen()的封裝(wrapper)。從Python2.4開始使用Popen來建立進程,用於串連到子進程的標準輸入/輸出/錯誤中去,還可以得到子進程的傳回值。這些封裝的目的在於讓我們容易使用子進程。當我們想要更個人化我們的需求的時候,就要轉向Popen類,該類產生的對象用來代表子進程。

建構函式如下:

subprocess.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)

與上面的封裝不同,Popen對象建立後,主程式不會自動等待子進程完成。我們必須調用對象的wait()方法,父進程才會等待 (也就是阻塞block)。

a) 不等待的子進程

#!/usr/bin/env pythonimport subprocesschild = subprocess.Popen([‘ping‘,‘-c‘,‘4‘,‘www.baidu.com‘])print ‘hello‘

執行結果:

[[email protected] script]# python sub.py hello[[email protected] script]# PING www.a.shifen.com (61.135.169.125) 56(84) bytes of data.64 bytes from 61.135.169.125: icmp_seq=1 ttl=55 time=2.04 ms64 bytes from 61.135.169.125: icmp_seq=2 ttl=55 time=1.58 ms64 bytes from 61.135.169.125: icmp_seq=3 ttl=55 time=2.22 ms64 bytes from 61.135.169.125: icmp_seq=4 ttl=55 time=2.13 ms--- www.a.shifen.com ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 3008msrtt min/avg/max/mdev = 1.580/1.995/2.220/0.251 ms

可以看出,Python並沒有等到child子進程執行的Popen操作完成就執行了print操作。

b) 添加子進程等待

#!/usr/bin/env pythonimport subprocesschild = subprocess.Popen([‘ping‘,‘-c‘,‘4‘,‘www.baidu.com‘])  #建立一個子進程,進程名為child,執行操作ping -c 4 www.baidu.comchild.wait()                             #子進程等待print ‘hello‘

執行結果:

[[email protected] script]# python sub.py PING www.a.shifen.com (61.135.169.125) 56(84) bytes of data.64 bytes from 61.135.169.125: icmp_seq=1 ttl=55 time=1.82 ms64 bytes from 61.135.169.125: icmp_seq=2 ttl=55 time=1.65 ms64 bytes from 61.135.169.125: icmp_seq=3 ttl=55 time=1.99 ms64 bytes from 61.135.169.125: icmp_seq=4 ttl=55 time=2.08 ms--- www.a.shifen.com ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 3009msrtt min/avg/max/mdev = 1.656/1.889/2.082/0.169 mshello

看出Python執行print操作是在child子進程操作完成以後才進行的。

此外,你還可以在父進程中對子進程進行其它操作,比如我們上面例子中的child對象:

child.poll() # 檢查子進程狀態child.kill() # 終止子進程child.send_signal() # 向子進程發送訊號child.terminate() # 終止子進程
ps: 子進程的PID儲存在child.pid

子進程文字資料流控制

子進程的標準輸入、標準輸出和標準錯誤如下屬性分別表示:

child.stdin | child.stdout | child.stderr

我們還可以在Popen()建立子進程的時候改變標準輸入、標準輸出和標準錯誤,並可以利用subprocess.PIPE將多個子進程的輸入和輸出串連在一起,構成管道(pipe),如下2個例子:

例1 
#!/usr/bin/env pythonimport subprocesschild = subprocess.Popen([‘ls‘,‘-l‘],stdout=subprocess.PIPE)    #將標準輸出定向輸出到subprocess.PIPEprint child.stdout.read() #使用 child.communicate() 也可

輸出結果:

[[email protected] script]# python sub.py total 12-rw-r--r--. 1 root root  36 Jan 23 07:38 analyse.sh-rw-r--r--. 1 root root 446 Jan 25 19:35 sub.py
例2#!/usr/bin/env pythonimport subprocesschild1 = subprocess.Popen([‘cat‘,‘/etc/passwd‘],stdout=subprocess.PIPE)child2 = subprocess.Popen([‘grep‘,‘root‘],stdin=child1.stdout,stdout=subprocess.PIPE)print child2.communicate()

輸出結果為

(‘root:x:0:0:root:/root:/bin/bash\n, None)

subprocess.PIPE實際上為文字資料流提供一個緩衝區。child1的stdout將文本輸出到緩衝區,隨後child2的stdin從該PIPE中將文本讀取走。child2的輸出文本也被存放在PIPE中,直到communicate()方法從PIPE中讀取出PIPE中的文本。
注意:communicate()是Popen對象的一個方法,該方法會阻塞父進程,直到子進程完成

子進程命令解釋

  在上面的例子中我們建立子進程時,全部是調用Python進行解釋,但Python並沒有將所有命令全部解釋,當Python不能進行解釋時,就緒要調用系統來進行執行。

#!/usr/bin/env pythonimport subprocesssubprocess.Popen([‘ls‘,‘-l‘])subprocess.Popen([‘ifconfig|grep 127.0.0.1‘],shell=True)

結果

>>> subprocess.Popen([‘ifconfig|grep 127.0.0.1‘],shell=True)<subprocess.Popen object at 0x7f25eb0c1350>>>>           inet addr:127.0.0.1  Mask:255.0.0.0

 

python之subprocess模組

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.