1. 程式人生 > >python之subprocess

python之subprocess

world imp oot int shell. root let nbsp 發送數據

官網介紹:https://docs.python.org/3/library/subprocess.html

Popen():
[[email protected] scripts]# cat sub_popen.py 
#!/usr/bin/python
#coding=utf8
import subprocess
child = subprocess.Popen([‘ls‘,‘-l‘],shell=True)
print(type(child))
print(‘parent‘)
[[email protected] scripts]# python sub_popen.py 
<class ‘subprocess.Popen‘>
parent
stu_subprocess.py  sub_popen.py

如果將不添加shell,使用默認的:
[[email protected]
/* */ 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‘) [[email protected] 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啟動新的進程與父進程並行執行,默認父進程不等待新進程結束。
[[email protected] 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())
[[email protected] 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
 
[[email protected]
/* */ 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() [[email protected] scripts]# python test_subprocess1.py 2017-08-21 16:49:15.061676 0 當子進程運行完成結束後,返回code為0 2017-08-21 16:49:25.066657 poll():判斷子進程是否結束 [[email protected] 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() [[email protected] 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(): 殺掉子進程 [[email protected] 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() [[email protected] scripts]# python test_subprocess3.py 2017-08-21 17:03:16.315531 2017-08-21 17:03:21.329266 可以看見子進程只運行了5秒
[[email protected] 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‘)
[[email protected] 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將文本輸出到緩存區,然後打印出緩存區的內容:
[[email protected] 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‘)
[[email protected] 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。
[[email protected] 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‘)
[[email protected] 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對象的一個方法,該方法會阻塞父進程,直到子進程完成
[[email protected] 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‘)
[[email protected] 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()實現交互:
[[email protected] 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‘)
[[email protected] scripts]# python stu_subprocess.py 
hello

parent
[[email protected] 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)
[[email protected] scripts]# python sub_popen2.py 
b‘hello\nworld\n‘
call():
subprocess.call()
父進程等待子進程完成
返回退出信息(returncode,相當於Linux exit code)
[[email protected] scripts]# cat sub_call.py 
#!/usr/bin/python
#coding=utf8
import subprocess
child = subprocess.call([‘ls‘,‘-l‘],shell=False)
print(type(child))
print(‘parent‘)
[[email protected] 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函數可以明顯看出子進程阻塞了主進程的運行,先運行子進程,最後才是主進程
[[email protected] 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‘)
[[email protected] 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類型:
[[email protected] 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只接受數組變量作為命令,並將數組的第一個元素作為命令,剩下的全部作為該命令的參數。
[[email protected] 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.
[[email protected] 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‘)
[[email protected] 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():
[[email protected] 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‘)
[[email protected] 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
 
[[email protected] 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‘)
[[email protected] scripts]# python sub_check_output.py
<class ‘bytes‘>
parent
並沒有打印出子進程運行後的內容
subprocess.getoutput(cmd),返回的是一個字符串
Return output (stdout and stderr) of executing cmd in a shell.
[[email protected] 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
[[email protected] 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()
[[email protected] 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()
[[email protected] 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‘)

python之subprocess