python常用模塊-調用系統命令模塊(subprocess)


                  python常用模塊-調用系統命令模塊(subprocess)

                                          作者:尹正傑

版權聲明:原創作品,謝絕轉載!否則將追究法律責任。

 

 

  subproces基本上就是為了取代os.system和os.spawn*模塊的。當我們需要調用系統命令的時候,最險考慮的os模塊。用os.system()和os.popen()來進行操作。但是這兩個命令過於簡單,不能完成一些復雜的操作,如給運行的命令提供輸入或者讀取命令的輸出,判斷該命令的運行狀態,管理多個命令的並行等等。這時subprocess中的popen命令就能有效的完成我們需要的操作。

   subprocess模塊允許一個進程創建一個新的子進程,通過管道連接到子進程的stdin/stdout/stderr,獲取子進程的返回值等操作。這個模塊只是一個類:popen。

 

 

一.初識subprocess

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 
 7 import subprocess
 8 
 9 cmd = subprocess.Popen("ping www.baidu.com",shell=True)                #開啟新的進程,執行“dir”命令。shell=True關鍵字是運行將命令和參數寫在一起,
10 
11 # cmd = subprocess.Popen(["ping","www.baidu.com"])                        #如果不加shell=True關鍵字則需要將命令和參數分開寫放在一個列表中。
12 
13 cmd.wait()                                                                #需要等待上面開啟的進程執行完畢才會繼續執行下面的代碼。
14 
15 print("-"*50,"ending","-"*50)
16 
17 print(cmd.poll())                                                    #查看子進程狀態
18 
19 cmd.kill()                                                          #終止子進程
20 
21 # cmd.send_signal()                                                       #向子進程發送信號
22 
23 cmd.terminate()                                                     #終止子進程。
24 
25 print(cmd.pid   )                                                          #查看子進程號
26 
27 
28 
29 
30 #以上代碼執行結果如需:
31 
32 ���� Ping www.baidu.com [61.135.169.125] ���� 32 �ֽڵ�����:
33 ���� 61.135.169.125 �Ļظ�: �ֽ�=32 ʱ��=7ms TTL=57
34 ���� 61.135.169.125 �Ļظ�: �ֽ�=32 ʱ��=3ms TTL=57
35 ���� 61.135.169.125 �Ļظ�: �ֽ�=32 ʱ��=7ms TTL=57
36 ���� 61.135.169.125 �Ļظ�: �ֽ�=32 ʱ��=4ms TTL=57
37 
38 61.135.169.125 �� Ping ͳ����Ϣ:
39     ���ݰ�: �ѷ��� = 4���ѽ��� = 4����ʧ = 0 (0% ��ʧ)��
40 �����г̵Ĺ���ʱ��(�Ժ���Ϊ��λ):
41     ��� = 3ms��� = 7ms��ƽ�� = 5ms
42 -------------------------------------------------- ending --------------------------------------------------
43 0
44 372

 

二.進程間通信-子進程的文本流控制

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 
 7 import subprocess
 8 
 9 
10 
11 cmd = subprocess.Popen("dir",shell=True,stdout=subprocess.PIPE)      #將輸出的內容傳給“PIPE”,也就是我們常說的管道。
12 
13 print(cmd.stdout.read().decode("gbk"))                                #將管道的內容讀取出來。
14 
15 
16 
17 
18 
19 #以上代碼執行結果如下:
20  驅動器 E 中的卷是 應用程序存放處
21  卷的序列號是 FAFC-64CF
22 
23  E:\Code\pycharm\文件存放處\python學習筆記\Day12 的目錄
24 
25 2018/03/16  22:37    <DIR>          .
26 2018/03/16  22:37    <DIR>          ..
27 2018/03/16  19:59               816 1.configparser模塊-創建文件.py
28 2018/03/16  20:07             1,150 2.讀操作.py
29 2018/03/16  20:21               464 3.修改配置文件.py
30 2018/03/16  20:26               728 4.configparser刪除的實例.py
31 2018/03/16  22:37             1,252 5.subprocess模塊.py
32 2018/03/16  22:36               492 6.進程間通信-子進程的文本流控制.py
33 2018/03/16  20:26               141 cfg.ini
34 2018/03/15  21:38                82 上課地址:
35                8 個文件          5,125 字節
36                2 個目錄 50,547,294,208 可用字節

 

三.subprocess.run實例

  subprocess.run調用shell命令,只能保存執行后的狀態,不能保存命令的執行結果!

 1 #不含參數的調用linux命令的方法
 2 >>> a = subprocess.run("df")                               
 3 Filesystem     1K-blocks    Used Available Use% Mounted on
 4 /dev/sda2        8854456 4170968   4227040  50% /
 5 tmpfs             502172     228    501944   1% /dev/shm
 6 /dev/sda1         289293   28463    245470  11% /boot
 7 
 8 #含參數的調用linux命令的方法
 9 >>> a = subprocess.run(["df","-h"])
10 Filesystem      Size  Used Avail Use% Mounted on
11 /dev/sda2       8.5G  3.8G  4.3G  48% /
12 tmpfs           491M  228K  491M   1% /dev/shm
13 /dev/sda1       283M   28M  240M  11% /boot
14 >>> 
15 
16 
17 
18 #調用復雜的linux命令的方法,需要加“shell=True”,表示將前面引號的內容放在一個終端(terminal)去執行,需要注意的是這個不能保存命令輸出的結果,而是保存命令執行的結果喲!一般非“0”就表示命令沒有執行成功,而結果是“0”表示執行命令實成功的,但是命令的輸出結果是無法保存的!切記!
19 >>> a = subprocess.run("df -h | grep /dev/sda1",shell=True)
20 /dev/sda1       283M   28M  240M  11% /boot
21 >>> a.returncode
22 0

 

四.subprocess.call與subprocess.check_call函數的調用方法

  執行命令,返回命令的執行狀態,“0” or 非 “0”。

 1 #執行命令,返回命令執行狀態 , 0 or 非0
 2 >>> retcode = subprocess.call(["ls", "-l"])
 3 total 96
 4 -rw-------. 1 root root  3321 Oct 13 10:26 anaconda-ks.cfg
 5 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Desktop
 6 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Documents
 7 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Downloads
 8 -rw-r--r--. 1 root root 41433 Oct 13 10:26 install.log
 9 -rw-r--r--. 1 root root  9154 Oct 13 10:24 install.log.syslog
10 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Music
11 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Pictures
12 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Public
13 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Templates
14 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Videos
15 >>>
16 
17 
18 #執行命令,如果命令結果為0,就正常返回,否則拋異常
19 >>> subprocess.check_call(["ls", "-l"])    
20 total 96
21 -rw-------. 1 root root  3321 Oct 13 10:26 anaconda-ks.cfg
22 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Desktop
23 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Documents
24 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Downloads
25 -rw-r--r--. 1 root root 41433 Oct 13 10:26 install.log
26 -rw-r--r--. 1 root root  9154 Oct 13 10:24 install.log.syslog
27 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Music
28 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Pictures
29 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Public
30 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Templates
31 drwxr-xr-x. 2 root root  4096 Oct 13 22:03 Videos
32 0
33 >>>

 

五.subprocess.getstatusoutput函數的調用方法

  接收字符串格式命令,返回元組形式,第1個元素是執行狀態,第2個是命令結果

1  >>> subprocess.getstatusoutput('ls /bin/pwd')
2  (0, '/bin/pwd')
3  >>>

 

六.subprocess.getoutput函數調用方法

  接收字符串格式命令,並返回結果.

1  >>> subprocess.getoutput('ifconfig | grep eth0')
2  'eth0      Link encap:Ethernet  HWaddr 00:0C:29:D4:DB:87  '
3  >>> 

 

七.subprocess.check_output函數調用方法

  執行命令,並返回結果,注意是返回結果,不是打印,下例結果返回給res.

1  >>> res=subprocess.check_output(['pwd'])    
2  >>> res
3  b'/root\n'
4  >>> 

 

八.subprocess.Popen函數用法

  上面那些方法,底層都是封裝的subprocess.Popen

 1 >>> p = subprocess.Popen("df -h|grep /dev/sda1",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
 2 >>> p.stdout.read()
 3 b'/dev/sda1       283M   28M  240M  11% /boot\n'
 4 >>> 
 5 
 6 “”“
 7 注意:
 8 我們來對第一行的進行講解一下
 9 subprocess.Popen表示打開一個終端(只是啟動一個進程),stdin=subprocess.PIPE表示輸入通過subprocess.PIPE這個管道傳輸,stdout=subprocess.PIPE表示輸出也通過subprocess.PIPE這個管道傳輸,stderr=subprocess.PIPE同理。
10 ”“”

 

九.檢查命令是否執行完畢

1.poll()方法調用案例【不需要等】

 1 >>> p = subprocess.Popen("top -bn 5",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
 2 >>> p.poll()
 3 >>> p.poll()
 4 >>> p.poll()
 5 >>> p.poll()
 6 >>> p.poll()
 7 >>> p.poll()
 8 0
 9 >>> p.poll()
10 0
11 >>> 
12 ‘’‘
13 poll()
14 Check if child process has terminated. Returns returncode
15 ’‘’

2.wait()方法調用案例【需要等】返回執行狀態

1 >>> p = subprocess.Popen("top -bn 5",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
2 >>> p.wait()
3 0
4 >>> 
5 
6 '''
7 wait()
8 Wait for child process to terminate. Returns returncode attribute.
9 '''

3.terminate()方法調用案例,直接殺掉啟動進程

1 >>> p = subprocess.Popen("top -bn 5",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) 
2 >>> p.poll()
3 >>> p.terminate()
4 >>> p.poll()     
5 143
6 
7 '''
8 terminate() 殺掉所啟動進程,此時p.poll返回值應該是非“0”,因為不是正常結束的!沒有執行完畢就被殺掉了。
9 '''

4.communicate()函數調用方法

 1 >>> p = subprocess.Popen("df -h;sleep 100",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
 2 >>> p.poll()       
 3 >>> p.poll()
 4 >>> p.communicate(timeout=2)
 5 Traceback (most recent call last):
 6   File "<stdin>", line 1, in <module>
 7   File "/usr/local/lib/python3.5/subprocess.py", line 1068, in communicate
 8     stdout, stderr = self._communicate(input, endtime, timeout)
 9   File "/usr/local/lib/python3.5/subprocess.py", line 1699, in _communicate
10     self._check_timeout(endtime, orig_timeout)
11   File "/usr/local/lib/python3.5/subprocess.py", line 1094, in _check_timeout
12     raise TimeoutExpired(self.args, orig_timeout)
13 subprocess.TimeoutExpired: Command 'df -h;sleep 100' timed out after 2 seconds
14 >>> 
15 
16 ‘’‘
17 communicate() 等待任務結束,我們需要在里面添加一個參數,默認單位是“s”,如果程序執行時間超過指定的時間就會拋出一個“TimeoutExpired”的字樣喲,不過我們可以用異常處理來吧這個錯誤解決掉!
18 ’‘’

5.preexec_fn參數調用案例

 1 >>> def name():
 2 ...     print("my name is yinzhengjie!")
 3 ... 
 4 >>> p = subprocess.Popen("pwd",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, preexec_fn=name)    >>> p.stdout.read()
 5 b'my name is yinzhengjie!\n/root\n'
 6 >>> 
 7 
 8 ‘’‘
 9 preexec_fn:只在Unix平台下有效,用於指定一個可執行對象(callable object),它將在子進程運行之前被調用,運行結果見上例。
10 ’‘’

6.cwd參數調用案例

1 >>> p = subprocess.Popen("pwd",cwd="/usr/local",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)  
2 >>> p.stdout.read()
3 b'/usr/local\n'
4 >>> 
5 
6 '''
7 cwd:用於設置子進程的當前目錄
8 '''

7.env參數調用案例

1 >>> p = subprocess.Popen("echo $name_str",cwd="/usr/local",shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,env={"name_str":"yinzhengjie"})
2 >>> p.stdout.read()
3 b'yinzhengjie\n'
4 >>> 
5 ‘’‘
6 提示:
7 env:用於指定子進程的環境變量。如果env = None,子進程的環境變量將從父進程中繼承。
8 ’‘’

 

 

 


免責聲明!

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



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