1. 程式人生 > >python3之subprocess常見方法使用

python3之subprocess常見方法使用

一、常見subprocess方法

1、subprocess.getstatusoutput(cmd)

官方解釋:

Return (exitcode, output) of executing cmd in a shell.

Execute the string 'cmd' in a shell with 'check_output' and
return a 2-tuple (status, output). The locale encoding is used
to decode the output and process newlines.

cmd可以直接執行shell命令,而不需要cmd命令以列表輸入----subprocess.getstatusoutput("cat /proc/meminfo")

返回值包含cmd的執行狀態和執行結果,可以直接賦值給某個變數

例項:

>>> ret = subprocess.getoutput('ls -l')
>>> print(ret)
總用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 視訊
drwxr-xr-x  2 wader wader   4096 12月  7  2015 圖片
drwxr
-xr-x 2 wader wader 4096 12月 7 2015 文件 drwxr-xr-x 2 wader wader 4096 4月 13 2016 下載 drwxr-xr-x 2 wader wader 4096 12月 7 2015 音樂 drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面 >>> retcode, output = subprocess.getstatusoutput('ls -l') >>> print(retcode) 0 >>> print(output) 總用量
160 drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的 drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板 drwxr-xr-x 2 wader wader 4096 12月 7 2015 視訊 drwxr-xr-x 2 wader wader 4096 12月 7 2015 圖片 drwxr-xr-x 2 wader wader 4096 12月 7 2015 文件 drwxr-xr-x 2 wader wader 4096 4月 13 2016 下載 drwxr-xr-x 2 wader wader 4096 12月 7 2015 音樂 drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面 >>> retcode, output = subprocess.getstatusoutput('ls -l /test') >>> print(retcode) 2 >>> print(output) ls: 無法訪問/test: 沒有那個檔案或目錄

 

 

2、subprocess.getoutput(cmd)

官方解釋:

Return output (stdout or stderr) of executing cmd in a shell.

Like getstatusoutput(), except the exit status is ignored and the return
value is a string containing the command's output

cmd可以直接執行shell命令,而不需要cmd命令以列表輸入---subprocess.getoutput("cat /proc/meminfo")
返回值包含cmd的執行結果,可以直接賦值給某個變數
功能和getstatusoutput類似

3、subprocess.run(*popenargs, input=None, timeout=None, check=False, **kwargs))

Run command with arguments and return a CompletedProcess instance.   執行傳入命令引數後,返回CompletedProcess例項
The returned instance will have attributes args, returncode, stdout and
stderr. By default, stdout and stderr are not captured, and those attributes
will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them.


check等於True的時候,當執行狀態不是0時,會丟擲CalledProcessError異常提示

傳入命令引數時,需要以多個命令拆分按照列表形式傳入:subprocess.run(['df', '-h'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)

如果傳入引數同時傳入shell=True,則傳入一個字串args,shell命令而不是待執行的shell命令序列

例項:
>>> subprocess.run(["ls", "-l"])  # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')
 

 

 

4、subprocess.call()

官方解釋:

Run command with arguments. Wait for command to complete or
timeout, then return the returncode attribute

 傳入shell命令引數格式subprocess.check_call(["ls""-l"])

如果傳入引數同時傳入shell=True,則可以傳入一個字串shell命令而不是待執行的shell命令列表--subprocess.check_call("exit 1", shell=True)
返回引數僅返回執行狀態碼,可通過把結果複製給某個變數檢視,如果直接在linux下python編譯器執行該命令會直接顯示命令執行的結果

例項:
>>> subprocess.call(['ls',  '-l'])
總用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 視訊
drwxr-xr-x  2 wader wader   4096 12月  7  2015 圖片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文件
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下載
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音樂
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
0
>>> subprocess.call('ls -l', shell=True)
總用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 視訊
drwxr-xr-x  2 wader wader   4096 12月  7  2015 圖片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文件
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下載
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音樂
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
0
>>> subprocess.call(['ls',  '-l'], stdout=subprocess.DEVNULL)
0
>>> subprocess.call(['ls',  '-l', '/test'])
ls: 無法訪問/test: 沒有那個檔案或目錄
2

 

5、subprocess.check_call()

官方解釋:

Run command with arguments.  Wait for command to complete.  If
the exit code was zero then return, otherwise raise
CalledProcessError. The CalledProcessError object will have the
return code in the returncode attribute.

check_call基本和call功能一樣,只是增加了返回狀態碼校驗,如果執行狀態碼是0,則返回0,否則丟擲異常

例項:

>>> subprocess.check_call(['ls',  '-l'])
總用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 視訊
drwxr-xr-x  2 wader wader   4096 12月  7  2015 圖片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文件
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下載
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音樂
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
0
>>> subprocess.check_call('ls -l', shell=True)
總用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 視訊
drwxr-xr-x  2 wader wader   4096 12月  7  2015 圖片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文件
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下載
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音樂
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
0
>>> subprocess.check_call('ls -l /test', shell=True)
ls: 無法訪問/test: 沒有那個檔案或目錄
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/subprocess.py", line 557, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'ls -l /test' returned non-zero exit status 2

 

6、subprocess.check_output()

官方解釋:

Run command with arguments and return its output.

If the exit code was non-zero it raises a CalledProcessError. The
CalledProcessError object will have the return code in the returncode
attribute and output in the output attribute.
執行命令,如果狀態碼是0,則返回執行結果,否則丟擲異常--
subprocess.check_output(["ls""-l"])
如果傳入引數同時傳入shell=True,則可以傳入一個字串shell命令而不是待執行的shell命令列表--
subprocess.check_call("exit 1", shell=True)
返回值包含cmd的執行結果,可以直接賦值給某個變數

例項:
>>> ret = subprocess.check_output(['ls',  '-l'])
>>> print(ret)
b' \xe5\x85\xac\xe5\x85\xb1\xe7\x9a\x84\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe6\xa8\xa1\xe6\x9d\xbf\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe8\xa7\x86\xe9\xa2\x91\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe5\x9b\xbe\xe7\x89\x87\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe6\x96\x87\xe6\xa1\xa3\ndrwxr-xr-x  2 wader wader   4096  4\xe6\x9c\x88 13  2016 \xe4\xb8\x8b\xe8\xbd\xbd\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe9\x9f\xb3\xe4\xb9\x90\ndrwxr-xr-x  7 wader wader   4096  5\xe6\x9c\x88 26  2016 \xe6\xa1\x8c\xe9\x9d\xa2\n'
>>> ret = subprocess.check_output(['ls',  '-l'], universal_newlines=True)
>>> print(ret)
總用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 視訊
drwxr-xr-x  2 wader wader   4096 12月  7  2015 圖片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文件
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下載
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音樂
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面

 

二、subprocess.Popen()類--用於執行復雜的系統命令

該類用於在一個新的程序中執行一個子程式。前面我們提到過,上面介紹的這些函式都是基於subprocess.Popen類實現的,通過使用這些被封裝後的高階函式可以很方面的完成一些常見的需求。由於subprocess模組底層的程序建立和管理是由Popen類來處理的,因此,當我們無法通過上面哪些高階函式來實現一些不太常見的功能時就可以通過subprocess.Popen類提供的靈活的api來完成。

1、subprocess.Popen的建構函式

def __init__(self, args, bufsize=-1, executable=None,
                 stdin=None, stdout=None, stderr=None,
                 preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
                 shell=False, cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0,
                 restore_signals=True, start_new_session=False,
                 pass_fds=(), *, encoding=None, errors=None)

建構函式詳細引數說明和其他實現過程可以參考對應subprocess庫檔案

引數說明:

  • args: 要執行的shell命令,可以是字串,也可以是命令各個引數組成的序列。當該引數的值是一個字串時,該命令的解釋過程是與平臺相關的,因此通常建議將args引數作為一個序列傳遞。
  • bufsize: 指定快取策略,0表示不緩衝,1表示行緩衝,其他大於1的數字表示緩衝區大小,負數 表示使用系統預設緩衝策略。
  • stdin, stdout, stderr: 分別表示程式標準輸入、輸出、錯誤控制代碼。
  • preexec_fn: 用於指定一個將在子程序執行之前被呼叫的可執行物件,只在Unix平臺下有效。
  • close_fds: 如果該引數的值為True,則除了0,1和2之外的所有檔案描述符都將會在子程序執行之前被關閉。
  • shell: 該引數用於標識是否使用shell作為要執行的程式,如果shell值為True,則建議將args引數作為一個字串傳遞而不要作為一個序列傳遞。
  • cwd: 如果該引數值不是None,則該函式將會在執行這個子程序之前改變當前工作目錄。
  • env: 用於指定子程序的環境變數,如果env=None,那麼子程序的環境變數將從父程序中繼承。如果env!=None,它的值必須是一個對映物件。
  • universal_newlines: 如果該引數值為True,則該檔案物件的stdin,stdout和stderr將會作為文字流被開啟,否則他們將會被作為二進位制流被開啟。
  • startupinfo和creationflags: 這兩個引數只在Windows下有效,它們將被傳遞給底層的CreateProcess()函式,用於設定子程序的一些屬性,如主視窗的外觀,程序優先順序等。

2. subprocess.Popen類的例項可呼叫的方法

方法 描述
Popen.poll() 用於檢查子程序(命令)是否已經執行結束,沒結束返回None,結束後返回狀態碼。
Popen.wait(timeout=None) 等待子程序結束,並返回狀態碼;如果在timeout指定的秒數之後程序還沒有結束,將會丟擲一個TimeoutExpired異常。
Popen.communicate(input=None, timeout=None) 該方法可用來與程序進行互動,比如傳送資料到stdin,從stdout和stderr讀取資料,直到到達檔案末尾。
Popen.send_signal(signal) 傳送指定的訊號給這個子程序。
Popen.terminate() 停止該子程序。
Popen.kill() 殺死該子程序。

關於communicate()方法的說明:

  • 該方法中的可選引數 input 應該是將被髮送給子程序的資料,或者如沒有資料傳送給子程序,該引數應該是None。input引數的資料型別必須是位元組串,如果universal_newlines引數值為True,則input引數的資料型別必須是字串。
  • 該方法返回一個元組(stdout_data, stderr_data),這些資料將會是位元組穿或字串(如果universal_newlines的值為True)。
  • 如果在timeout指定的秒數後該程序還沒有結束,將會丟擲一個TimeoutExpired異常。捕獲這個異常,然後重新嘗試通訊不會丟失任何輸出的資料。但是超時之後子程序並沒有被殺死,為了合理的清除相應的內容,一個好的應用應該手動殺死這個子程序來結束通訊。
  • 需要注意的是,這裡讀取的資料是緩衝在記憶體中的,所以,如果資料大小非常大或者是無限的,就不應該使用這個方法

3. subprocess.Popen使用例項

例項1、

>>> import subprocess
>>>
>>> p = subprocess.Popen('df -Th', stdout=subprocess.PIPE, shell=True)
>>> print(p.stdout.read())
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/vda1      ext4       40G   12G   26G  31% /
devtmpfs       devtmpfs  3.9G     0  3.9G   0% /dev
tmpfs          tmpfs     3.9G     0  3.9G   0% /dev/shm
tmpfs          tmpfs     3.9G  386M  3.5G  10% /run
tmpfs          tmpfs     3.9G     0  3.9G   0% /sys/fs/cgroup
tmpfs          tmpfs     783M     0  783M   0% /run/user/0
tmpfs          tmpfs     783M     0  783M   0% /run/user/1000

例項2

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> obj.stdin.write('print(1) \n')
>>> obj.stdin.write('print(2) \n')
>>> obj.stdin.write('print(3) \n')
>>> out,err = obj.communicate()
>>> print(out)
1
2
3

>>> print(err)

例項3

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out,err = obj.communicate(input='print(1) \n')
>>> print(out)
1

>>> print(err)

例項4

實現類似df -Th | grep data命令的功能,實際上就是實現shell中管道的共功能

>>> 
>>> p1 = subprocess.Popen(['df', '-Th'], stdout=subprocess.PIPE)
>>> p2 = subprocess.Popen(['grep', 'data'], stdin=p1.stdout, stdout=subprocess.PIPE)
>>> out,err = p2.communicate()
>>> print(out)
/dev/vdb1      ext4      493G  4.8G  463G   2% /data
/dev/vdd1      ext4     1008G  420G  537G  44% /data1
/dev/vde1      ext4      985G  503G  432G  54% /data2

>>> print(err)
None

三、總結

那麼我們到底該用哪個模組、哪個函式來執行命令與系統及系統進行互動呢?下面我們來做個總結:

1、如果你的應用使用的Python 2.4以上,但是是Python 3.5以下的版本,Python官方給出的建議是使用subprocess.call()函式。Python 2.5中新增了一個subprocess.check_call()函式,Python 2.7中新增了一個subprocess.check_output()函式,這兩個函式也可以按照需求進行使用

2、如果你的應用使用的是Python 3.5及以上的版本(目前應該還很少),Python官方給出的建議是儘量使用subprocess.run()函式

3、當subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()這些高階函式無法滿足需求時,我們可以使用subprocess.Popen類來實現我們需要的複雜功能

不過經過個人試驗認為getoutput、getstatusoutput方法使用比較便捷,subprocess適合個性化的執行

參考連結:https://www.cnblogs.com/yyds/p/7288916.html