使用subprocessm模块管理进程
?subprocess被用來替換一些老的模塊和函數,如:os.system、os.spawn*、os.popen*、popen2.*、commands.*。
subprocess的目的就是啟動一個新的進程并且與之通信。
1.Popen
subprocess模塊中只定義了一個類: 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)
其參數解釋如下所示:
| 參數 | 說明 |
| args | 字符串或者列表 |
| bufsize | 0 無緩沖 |
| executable | 一般不用吧,args字符串或列表第一項表示程序名 |
| stdin | None 沒有任何重定向,繼承父進程 |
| preexec_fn | 鉤子函數, 在fork和exec之間執行。(unix) |
| close_fds | unix 下執行新進程前是否關閉0/1/2之外的文件 |
| shell | 為真的話 |
| cwd | 設置工作目錄 |
| env | 設置環境變量 |
| universal_newlines | 各種換行符統一處理成 '\n' |
| startupinfo | window下傳遞給CreateProcess的結構體 |
| creationflags | windows下,傳遞CREATE_NEW_CONSOLE創建自己的控制臺窗口 |
?
(1)子進程的簡單控制
例 1#!/usr/bin/python3 import subprocess pingP = subprocess.Popen(args='ping -n 4 www.baidu.com',shell=True) print(pingP.pid) print(pingP.returncode)
執行結果如下所示:
D:\workspace\Python\python3\practise\subprocess>python3 demo01.py 2356 NoneD:\workspace\Python\python3\practise\subprocess> Pinging www.a.shifen.com [115.239.210.27] with 32 bytes of data: Reply from 115.239.210.27: bytes=32 time=9ms TTL=57 Reply from 115.239.210.27: bytes=32 time=11ms TTL=57 Reply from 115.239.210.27: bytes=32 time=26ms TTL=57 Reply from 115.239.210.27: bytes=32 time=7ms TTL=57Ping statistics for 115.239.210.27:Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds:Minimum = 7ms, Maximum = 26ms, Average = 13ms從輸出可以看出,代碼生產了一個子進程并執行了args中指定的命令,然后執行下面的語句。由于網絡應用的延遲,這就使得在打印出了進程ID和返回值后才輸出外部命令的輸出。
由于外部程序是在一個新生成的子程序中執行的,所以如果不加以限制,則有可能回將原進程和子進程的輸出混淆。如果需要等待該子進程結束,可以使用Popen類中的wait()函數,如下面的代碼所示:
例2#!/usr/bin/python3 import subprocess pingP = subprocess.Popen(args='ping -n 4 www.baidu.com',shell=True) pingP.wait() #等待進程完成 print(pingP.pid) print(pingP.returncode)
執行結果如下所示:
D:\workspace\Python\python3\practise\subprocess>python3 demo01.pyPinging www.a.shifen.com [115.239.210.27] with 32 bytes of data: Reply from 115.239.210.27: bytes=32 time=14ms TTL=57 Reply from 115.239.210.27: bytes=32 time=7ms TTL=57 Reply from 115.239.210.27: bytes=32 time=6ms TTL=57 Reply from 115.239.210.27: bytes=32 time=17ms TTL=57Ping statistics for 115.239.210.27:Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds:Minimum = 6ms, Maximum = 17ms, Average = 11ms 18508 0wait()函數將等待子進程的完成,將會返回子進程的返回值。
?從上面的輸出中可以看到,現在子進程的進程ID和返回值已經在子進程輸出的后面了。同時,子進程的返回值已經變為0,表示子進程已經順利退出。
?此外,你還可以在父進程中對子進程進行其它操作,比如我們上面例子中的child對象:
pingP.poll() # 檢查子進程狀態 pingP.kill() # 終止子進程 pingP.send_signal() # 向子進程發送信號 pingP.terminate() # 終止子進程 ps: 子進程的PID存儲在child.pid(2) 子進程文本流控制
在上面的兩個示例程序中,子進程被創建后,其標準輸入、標準輸出和標準錯誤處理都和原進程沒有關系。如果要管理子進程的輸入輸出,可以改變Popen類中的stdin、stdout和stderr等類參數。如何使用以前的進程創建方法,則需要將輸入輸出重定向。
例 3#!/usr/bin/python3 import subprocesspingP = subprocess.Popen(args='ping -n 4 www.baidu.com',shell=True,stdout = subprocess.PIPE) pingP.wait() print(pingP.stdout.read()) #讀取進程的輸出信息, print(pingP.pid) print(pingP.returncode)
代碼說明:
- 在Popen的類參數中,stdin、stdout、stderr分別用來指定程序標準輸入、標準輸出和標準錯誤的處理器,其值可以為PIPE、文件描述符和None等。默認值都為None。
- 在獲取輸出后,pingP.stdout(<open file '<fdopen>',mode 'rb'>)成為一個可讀的文件對象,可以使用相應的文件操作函數來讀取。
單單從輸出來看,例2和例3的輸出是一樣的。但是,兩者是完全不同的。在例2中,子進程的輸出并沒有得到控制。而在例3中,其子進程的輸出則被收集起來了。如果將腳本中的“print(pingP.stdout.read())”這句注釋掉,則程序輸出如下:
D:\workspace\Python\python3\practise\subprocess>python3 demo01.py 15404 0另外一種方式是采用Popen類提供的communicate方法。示例如下
#!/usr/bin/env python import subprocessch1 = subprocess.Popen(['cat','/etc/passwd'],stdout=subprocess.PIPE) ch2 = subprocess.Popen(['grep','root'],stdin=ch1.stdout,stdout=subprocess.PIPE)res = ch2.communicate() print(res)輸出結果為:
('root:x:0:0:root:/root:/bin/bash\n', None)subprocess.PIPE實際上為文本流提供一個緩存區。ch1的stdout將文本輸出到緩存區,隨后ch2的stdin從該PIPE中將文本讀取走。ch2的輸出文本也被存放在PIPE中,直到communicate()方法從PIPE中讀取出PIPE中的文本。
communicate()方法返回的是一個(stdout,sterr)元組。需要注意的是,communicate()是Popen對象的一個方法,該方法會阻塞父進程,直到子進程完成。同時,因為數據都是緩存在內存中的,所以如果數據很大的時候不要使用這個方法。
?
轉載于:https://www.cnblogs.com/bdhk/p/7440556.html
總結
以上是生活随笔為你收集整理的使用subprocessm模块管理进程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BZOJ1452 [JSOI2009]C
- 下一篇: 2-4 js基础-事件对象小结