官網介紹:https://docs.python.org/3/library/subprocess.html
Popen(): [root@oracle scripts]# cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen(['ls','-l'],shell=True) print(type(child)) print('parent') [root@oracle scripts]# python sub_popen.py <class 'subprocess.Popen'> parent stu_subprocess.py sub_popen.py 如果將不新增shell,使用預設的: [root@oracle scripts]# cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen(['ls','-l'],shell=False) shell引數預設為False print(type(child)) print('parent') [root@oracle scripts]# python sub_popen.py <class 'subprocess.Popen'> parent total 8 -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py -rw-r--r-- 1 root root 136 Aug 21 15:41 sub_popen.py Popen不會阻塞父程式執行,Popen啟動新的程式與父程式並行執行,預設父程式不等待新程式結束。
[root@oracle scripts]# cat test_subprocess.py #!/usr/bin/python #coding=utf8 def TestPopen(): import subprocess p = subprocess.Popen(['ls','-l'],shell=True) for i in range(5): print("other things") print(TestPopen()) [root@oracle scripts]# python test_subprocess.py other things other things other things other things other things None stu_subprocess.py sub_call.py sub_check_output.py sub_popen.py sub_run.py test_subprocess.py [root@oracle scripts]# cat test_subprocess1.py #!/usr/bin/python #coding=utf8 wait(): 阻塞父程式,等待子程式執行結束再繼續執行父程式 def TestWait(): import subprocess import datetime print(datetime.datetime.now()) p = subprocess.Popen('sleep 10',shell=True) p.wait() wait()阻塞了父程式的執行,等待子程式執行完成後才繼續執行父程式 print(p.returncode) print(datetime.datetime.now()) TestWait() [root@oracle scripts]# python test_subprocess1.py 2017-08-21 16:49:15.061676 0 當子程式執行完成結束後,返回code為0 2017-08-21 16:49:25.066657 poll():判斷子程式是否結束 [root@oracle scripts]# cat test_subprocess2.py #!/usr/bin/python #coding=utf8 def TestWait(): import subprocess import datetime,time print(datetime.datetime.now()) p = subprocess.Popen('sleep 10',shell=True) 子程式要睡眠10秒 t = 1 while (t <= 5): time.sleep(1) p.poll() 執行判斷子程式,這裡花了5秒 print(p.returncode) t = t + 1 print(datetime.datetime.now()) TestWait() [root@oracle scripts]# python test_subprocess2.py 2017-08-21 16:56:33.672417 None None None None None 2017-08-21 16:56:38.684795 kill()或者terminate(): 殺掉子程式 [root@oracle scripts]# cat test_subprocess3.py #!/usr/bin/python #coding=utf8 def TestKillAndTerminate(): import subprocess import datetime,time print(datetime.datetime.now()) p = subprocess.Popen('sleep 10',shell=True) t = 1 while (t <= 5): time.sleep(1) t = t + 1 p.kill() print(datetime.datetime.now()) TestKillAndTerminate() [root@oracle scripts]# python test_subprocess3.py 2017-08-21 17:03:16.315531 2017-08-21 17:03:21.329266 可以看見子程式只執行了5秒
[root@oracle scripts]# cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen(['ls','-l'],shell=False) child.wait() 阻塞父程式,直到子程式執行完成 print(type(child)) print('parent') [root@oracle scripts]# python sub_popen.py total 12 -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py -rw-r--r-- 1 root root 135 Aug 21 15:47 sub_call.py -rw-r--r-- 1 root root 149 Aug 21 15:47 sub_popen.py <class 'subprocess.Popen'> parent 可以看出先執行的子程式,最後才是父程式,等待子程式執行後,再執行父程式 除了wait()之外還有如下: child.poll() # 檢查子程式狀態 child.kill() # 終止子程式 child.send_signal() # 向子程式傳送訊號 child.terminate() # 終止子程式 子程式的PID儲存在child.pid 子程式的標準輸入、標準輸出和標準錯誤如下屬性分別表示: child.stdin child.stdout child.stderr
subprocess.PIPE實際上為文字流提供一個快取區。child的stdout將文字輸出到快取區,然後列印出快取區的內容: [root@oracle scripts]# cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen(['ls','-l'],shell=False,stdout=subprocess.PIPE) print(child.stdout.read().decode('utf-8')) 列印快取區內容,由於是bytes格式,所以轉碼 print('parent') [root@oracle scripts]# python sub_popen.py total 16 -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py -rw-r--r-- 1 root root 183 Aug 21 16:07 sub_popen.py -rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py parent
communicate() Popen.communicate(input=None):與子程式進行互動。向stdin傳送資料,或從stdout和stderr中讀取資料。可選引數input指定傳送到子程式的引數。Communicate()返回一個元組:(stdoutdata, stderrdata)。注意:如果希望通過程式的stdin向其傳送資料,在建立Popen物件的時候,引數stdin必須被設定為PIPE。同樣,如果希望從stdout和stderr獲取資料,必須將stdout和stderr設定為PIPE。 [root@oracle scripts]# cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen(['ls','-l'],shell=False,stdout=subprocess.PIPE) #print(child.stdout.read().decode('utf-8')) print(child.communicate()) 返回的是標準輸出,標準錯誤輸出的tuple print('parent') [root@oracle scripts]# python sub_popen.py (b'total 16\n-rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py\n-rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py\n-rw-r--r-- 1 root root 211 Aug 21 16:11 sub_popen.py\n-rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py\n', None) NONE就是標準錯誤輸出結果 parent 可以看見先輸出的子程式內容,然後才是父程式,communicate()是Popen物件的一個方法,該方法會阻塞父程式,直到子程式完成 [root@oracle scripts]# cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child1 = subprocess.Popen(['cat','/etc/passwd'],shell=False,stdout=subprocess.PIPE) child2 = subprocess.Popen(['grep','0:0'],stdin=child1.stdout, stdout=subprocess.PIPE) # subprocess.PIPE實際上為文字流提供一個快取區。child1的stdout將文字輸出到快取區,隨後child2的stdin從該PIPE中將文字讀取走。child2的輸出文字也被存放在PIPE中,直到communicate()方法從PIPE中讀取出PIPE中的文字。 out,err = child2.communicate() 因為communicate()返回的是一個元祖 print(out) 紙列印出標準輸出內容 print('parent') [root@oracle scripts]# python sub_popen.py b'root:x:0:0:root:/root:/bin/bash\n' parent child1.stdout-->subprocess.PIPE child2.stdin<--subprocess.PIPE child2.stdout-->subprocess.PIPE 利用communicate()實現互動: [root@oracle scripts]# cat stu_subprocess.py #!/usr/bin/python #coding=utf8 import subprocess child1 = subprocess.Popen(['python'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE) out,err = child1.communicate(b'print("hello")\nexit()') 繼續給子程式輸入資訊 # 啟動一個子程式,然後控制其輸入和輸出 print(out.decode('utf-8')) print('parent') [root@oracle scripts]# python stu_subprocess.py hello parent
[root@oracle scripts]# cat sub_popen2.py #!/usr/bin/python #coding=utf8 import subprocess obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) obj.stdin.write(b'print("hello")\n') stdin.write和communicate兩者交換使用 obj.stdin.write(b'print("world")') out,err = obj.communicate() print(out) [root@oracle scripts]# python sub_popen2.py b'hello\nworld\n'
call(): subprocess.call() 父程式等待子程式完成 返回退出資訊(returncode,相當於Linux exit code) [root@oracle scripts]# cat sub_call.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.call(['ls','-l'],shell=False) print(type(child)) print('parent') [root@oracle scripts]# python sub_call.py total 12 -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py -rw-r--r-- 1 root root 135 Aug 21 15:45 sub_call.py -rw-r--r-- 1 root root 136 Aug 21 15:41 sub_popen.py <class 'int'> call函式返回的是int parent 呼叫call函式可以明顯看出子程式阻塞了主程式的執行,先執行子程式,最後才是主程式 [root@oracle scripts]# cat sub_call.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.call(['ls','-l'],shell=False) print(type(child)) print(child) ----->returncode print('parent') [root@oracle scripts]# python sub_call.py total 12 -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py -rw-r--r-- 1 root root 149 Aug 21 15:47 sub_popen.py <class 'int'> 0 parent subprocess.call(*popenargs, **kwargs):執行命令。該函式將一直等待到子程式執行結束,並返回程式的returncode。如果子程式不需要進行互動,就可以使用該函式來建立。 call函式返回的是returncode,也就是int型別 根據shell型別不同,可以更改傳入call函式的args型別: [root@oracle scripts]# cat sub_call.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.call("ls -l",shell=True) print(type(child)) print(child) print('parent') shell=True引數會讓subprocess.call接受字串型別的變數作為命令,並呼叫shell去執行這個字串,當shell=False是,subprocess.call只接受陣列變數作為命令,並將陣列的第一個元素作為命令,剩下的全部作為該命令的引數。 [root@oracle scripts]# python sub_call.py total 40 -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py -rw-r--r-- 1 root root 143 Aug 21 17:22 sub_call.py -rw-r--r-- 1 root root 143 Aug 21 16:33 sub_check_output.py -rw-r--r-- 1 root root 162 Aug 21 17:17 sub_getoutput.py -rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py -rw-r--r-- 1 root root 148 Aug 21 16:29 sub_run.py -rw-r--r-- 1 root root 257 Aug 21 16:53 test_subprocess1.py -rw-r--r-- 1 root root 340 Aug 21 16:52 test_subprocess2.py -rw-r--r-- 1 root root 332 Aug 21 17:03 test_subprocess3.py -rw-r--r-- 1 root root 183 Aug 21 16:44 test_subprocess.py <class 'int'> 0 parent 所以當shell預設為False時,args傳入的值必須是列表,而不能是str from subprocess import call import shlex cmd = "cat test.txt; rm test.txt" call(cmd, shell=True) shell介紹: https://zhidao.baidu.com/question/651286079254739125.html
3.5新增的run(): class subprocess.CompletedProcess The return value from run(), representing a process that has finished. [root@oracle scripts]# cat sub_run.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.run(['ls','-l'],shell=False) print(type(child)) print(child) print('parent') [root@oracle scripts]# python sub_run.py total 16 -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py -rw-r--r-- 1 root root 149 Aug 21 15:47 sub_popen.py -rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py <class 'subprocess.CompletedProcess'> CompletedProcess(args=['ls', '-l'], returncode=0) parent
check_output(): [root@oracle scripts]# cat sub_check_output.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.check_output(['ls','-l'],shell=False) print(type(child)) print(child) print('parent') [root@oracle scripts]# python sub_check_output.py <class 'bytes'> b'total 20\n-rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py\n-rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py\n-rw-r--r-- 1 root root 156 Aug 21 16:26 sub_check_output.py\n-rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py\n-rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py\n' parent [root@oracle scripts]# cat sub_check_output.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.check_output(['ls','-l'],shell=False) print(type(child)) print('parent') [root@oracle scripts]# python sub_check_output.py <class 'bytes'> parent 並沒有列印出子程式執行後的內容
subprocess.getoutput(cmd),返回的是一個字串 Return output (stdout and stderr) of executing cmd in a shell. [root@oracle scripts]# python sub_getoutput.py <class 'str'> stu_subprocess.py sub_call.py sub_check_output.py sub_getoutput.py sub_popen.py sub_run.py test_subprocess1.py test_subprocess2.py test_subprocess3.py test_subprocess.py [root@oracle scripts]# cat sub_getoutput.py #!/usr/bin/python #coding=utf8 import subprocess def TestGetOutput(): outp = subprocess.getoutput(["ls" ,"-l"]) 列表 print(type(outp)) print(outp) TestGetOutput() [root@oracle scripts]# cat sub_getoutput.py #!/usr/bin/python #coding=utf8 import subprocess def TestGetOutput(): outp = subprocess.getoutput("ls -l") 字串 print(type(outp)) print(outp) TestGetOutput() [root@oracle scripts]# python sub_getoutput.py <class 'str'> total 40 -rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py -rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py -rw-r--r-- 1 root root 143 Aug 21 16:33 sub_check_output.py -rw-r--r-- 1 root root 162 Aug 21 17:17 sub_getoutput.py -rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py -rw-r--r-- 1 root root 148 Aug 21 16:29 sub_run.py -rw-r--r-- 1 root root 257 Aug 21 16:53 test_subprocess1.py -rw-r--r-- 1 root root 340 Aug 21 16:52 test_subprocess2.py -rw-r--r-- 1 root root 332 Aug 21 17:03 test_subprocess3.py -rw-r--r-- 1 root root 183 Aug 21 16:44 test_subprocess.py
#接收字串格式命令,返回元組形式,第1個元素是執行狀態,第2個是命令結果 >>> subprocess.getstatusoutput('ls -l') (0, 'total 40\n-rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py\n-rw-r--r-- 1 root root 143 Aug 21 17:22 sub_call.py\n-rw-r--r-- 1 root root 143 Aug 21 16:33 sub_check_output.py\n-rw-r--r-- 1 root root 162 Aug 21 17:17 sub_getoutput.py\n-rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py\n-rw-r--r-- 1 root root 148 Aug 21 16:29 sub_run.py\n-rw-r--r-- 1 root root 257 Aug 21 16:53 test_subprocess1.py\n-rw-r--r-- 1 root root 340 Aug 21 16:52 test_subprocess2.py\n-rw-r--r-- 1 root root 332 Aug 21 17:03 test_subprocess3.py\n-rw-r--r-- 1 root root 183 Aug 21 16:44 test_subprocess.py')