subprocess 模組的介紹與使用

零下一度
發布: 2017-07-23 13:46:44
原創
9482 人瀏覽過

一、subprocess以及常用的封裝函數
運行python的時候,我們都是在建立並執行一個行程。像Linux進程那樣,一個行程可以fork一個子進程,並讓這個子進程exec另外一個程式。在Python中,我們透過標準函式庫中的subprocess套件來fork一個子進程,並執行一個外部的程式。
subprocess套件中定義有幾個創建子進程的函數,這些函數分別以不同的方式建立子進程,所以我們可以根據需要來從中選取一個使用。另外subprocess也提供了一些管理標準流(standard stream)和管道(pipe)的工具,從而在進程間使用文字通訊。

subprocess.call()
父程式等待子程序完成
返回退出訊息(returncode,相當於Linux exit code)

subprocess.check_call()
父進程等待子進程完成
返回0
檢查退出訊息,如果returncode不為0,則舉出錯誤subprocess.CalledProcessError,物件包含returncode屬性,可用try…except…來檢查

subprocess.check_output()
父進程等待子進程完成
返回子進程向標準輸出的輸出結果
檢查退出訊息,如果returncode不為0,則舉出錯誤subprocess.CalledProcessError,該對象包含有returncode屬性和output屬性,output屬性為標準輸出的輸出結果,可用try…except…來檢查。

一、介紹

  subprocess最早在2.4版本引進。用來產生子進程,並可以透過​​管道連接他們的輸入/輸出/錯誤,以及獲得他們的返回值。

  subprocess用來取代多個舊模組和函數:

  • ##os.system

  • #os.spawn*
  • #os.popen*

#os.popen*

##popen2.*

commands.*

  運行python的時候,我們都是在創建並運行一個進程,linux中一個進程可以fork一個子進程,並且讓這個子進程exec另外一個程式。在python中,我們透過標準函式庫中的subprocess套件來fork一個子進程,並且執行一個外部的程式。 subprocess套件中定義有數個創建子進程的函數,這些函數分別以不同的方式建立子進程,所欲我們可以根據需要來從中選取一個使用。另外subprocess也提供了一些管理標準流(standard stream)和管道(pipe)的工具,從而在進程間使用文字通訊。

二、舊有模組的使用

#1.os.system()執行作業系統的指令,將結果輸出到螢幕,只回傳指令執行狀態(0:成功,非0 :失敗)

import os

>>> a = os.system("df -Th")
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/sda3      ext4   1.8T  436G  1.3T  26% /
tmpfs          tmpfs   16G     0   16G   0% /dev/shm
/dev/sda1      ext4   190M  118M   63M  66% /boot

>>> a
0         # 0 表示执行成功


# 执行错误的命令
>>> res = os.system("list")
sh: list: command not found
>>> res
32512       # 返回非 0 表示执行错误
登入後複製

  

2. os.popen()

執行作業系統的指令,會將結果儲存在記憶體當中,可以用read()方法讀取出來

#

import os

>>> res = os.popen("ls -l")

# 将结果保存到内存中
>>> print res
<open file &#39;ls -l&#39;, mode &#39;r&#39; at 0x7f02d249c390>

# 用read()读取内容
>>> print res.read()
total 267508
-rw-r--r--  1 root root    260968 Jan 27  2016 AliIM.exe
-rw-------. 1 root root      1047 May 23  2016 anaconda-ks.cfg
-rw-r--r--  1 root root   9130958 Nov 18  2015 apache-tomcat-8.0.28.tar.gz
-rw-r--r--  1 root root         0 Oct 31  2016 badblocks.log
drwxr-xr-x  5 root root      4096 Jul 27  2016 certs-build
drwxr-xr-x  2 root root      4096 Jul  5 16:54 Desktop
-rw-r--r--  1 root root      2462 Apr 20 11:50 Face_24px.ico
登入後複製

##  

# 三、subprocess模組

1、subprocess.run()

>>> import subprocess
# python 解析则传入命令的每个参数的列表
>>> subprocess.run(["df","-h"])
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-LogVol00
                      289G   70G  204G  26% /
tmpfs                  64G     0   64G   0% /dev/shm
/dev/sda1             283M   27M  241M  11% /boot
CompletedProcess(args=[&#39;df&#39;, &#39;-h&#39;], returncode=0)

# 需要交给Linux shell自己解析,则:传入命令字符串,shell=True
>>> subprocess.run("df -h|grep /dev/sda1",shell=True)
/dev/sda1             283M   27M  241M  11% /boot
CompletedProcess(args=&#39;df -h|grep /dev/sda1&#39;, returncode=0)
登入後複製

  

2 、subprocess.call()
執行指令,傳回指令的結果和執行狀態,0或非0

>>> res = subprocess.call(["ls","-l"])
总用量 28
-rw-r--r--  1 root root     0 6月  16 10:28 1
drwxr-xr-x  2 root root  4096 6月  22 17:48 _1748
-rw-------. 1 root root  1264 4月  28 20:51 anaconda-ks.cfg
drwxr-xr-x  2 root root  4096 5月  25 14:45 monitor
-rw-r--r--  1 root root 13160 5月   9 13:36 npm-debug.log

# 命令执行状态
>>> res
0
登入後複製

  

#3、subprocess. check_call()

執行指令,回傳結果與狀態,正常為0 ,執行錯誤則拋出例外
>>> subprocess.check_call(["ls","-l"])
总用量 28
-rw-r--r--  1 root root     0 6月  16 10:28 1
drwxr-xr-x  2 root root  4096 6月  22 17:48 _1748
-rw-------. 1 root root  1264 4月  28 20:51 anaconda-ks.cfg
drwxr-xr-x  2 root root  4096 5月  25 14:45 monitor
-rw-r--r--  1 root root 13160 5月   9 13:36 npm-debug.log
0

>>> subprocess.check_call(["lm","-l"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 537, in check_call
    retcode = call(*popenargs, **kwargs)
  File "/usr/lib64/python2.7/subprocess.py", line 524, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
登入後複製

  

#4、subprocess. getstatusoutput()

接受字串形式的指令,傳回一個元組形式的結果,第一個元素是指令執行狀態,第二個為執行結果

#执行正确
>>> subprocess.getstatusoutput(&#39;pwd&#39;)
(0, &#39;/root&#39;)

#执行错误
>>> subprocess.getstatusoutput(&#39;pd&#39;)
(127, &#39;/bin/sh: pd: command not found&#39;)
登入後複製

  

5、subprocess.getoutput()

接受字串形式的指令,放回執行結果

#
>>> subprocess.getoutput(&#39;pwd&#39;)
&#39;/root&#39;
登入後複製

  

6、subprocess.check_output()

執行指令,傳回執行的結果,而不是列印

#
>>> res = subprocess.check_output("pwd")
>>> res
b&#39;/root\n&#39; # 结果以字节形式返回
登入後複製

#四、subprocess.Popen()

#其實以上subprocess所使用的方法,都是subprocess.Popen的封裝,下面我們就來看看這個Popen方法。

###1、stdout############標準輸出######### ######
>>> res = subprocess.Popen("ls /tmp/yum.log", shell=True, stdout=subprocess.PIPE)  # 使用管道
>>> res.stdout.read()    # 标准输出
b&#39;/tmp/yum.log\n&#39;

res.stdout.close()   # 关闭
登入後複製
##################################################################### # ######  ######2、stderr#######標準錯誤######
>>> import subprocess
>>> res = subprocess.Popen("lm -l",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
# 标准输出为空
>>> res.stdout.read()
b&#39;&#39;

#标准错误中有错误信息
>>> res.stderr.read()
b&#39;/bin/sh: lm: command not found\n&#39;
登入後複製
###

  

注意:上面的提到的标准输出都为啥都需要等于subprocess.PIPE,这个又是啥呢?原来这个是一个管道,这个需要画一个图来解释一下:

4、poll()

定时检查命令有没有执行完毕,执行完毕后返回执行结果的状态,没有执行完毕返回None

>>> res = subprocess.Popen("sleep 10;echo &#39;hello&#39;",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> print(res.poll())
None
>>> print(res.poll())
None
>>> print(res.poll())
0
登入後複製

  

5、wait()

等待命令执行完成,并且返回结果状态

>>> obj = subprocess.Popen("sleep 10;echo &#39;hello&#39;",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> obj.wait()


# 中间会一直等待


0
登入後複製

  

6、terminate()

结束进程

import subprocess

>>> res = subprocess.Popen("sleep 20;echo &#39;hello&#39;",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> res.terminate()  # 结束进程
>>> res.stdout.read() 
b&#39;&#39;
登入後複製

7、pid

获取当前执行子shell的程序的进程号

import subprocess

>>> res = subprocess.Popen("sleep 5;echo &#39;hello&#39;",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> res.pid  # 获取这个linux shell 的 进程号
2778
登入後複製

以上是subprocess 模組的介紹與使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!