天天看點

python 運作shell指令的幾種方法(os.system、os.popen、subprocess、commands)1、os.system2、os.popen3、subprocess 子產品4、commands子產品

1、os.system

該函數傳回指令執行結果的傳回值,并不是傳回指令的執行輸出,

system()函數在執行過程中進行了以下三步操作: 1.fork一個子程序; 2.在子程序中調用exec函數去執行指令; 3.在父程序中調用wait(阻塞)去等待子程序結束。

對于fork失敗,system()函數傳回-1。 ****

用法示例

>>> os.system('ls -a')
.  ..  .bash_logout  .bash_profile  .bashrc  # 執行指令的标準輸出
0  # 傳回值
           

注意:system是阻塞的

2、os.popen

os.popen(command[, mode[, bufsize]])
           

參數

command – 使用的指令。

mode – 模式權限可以是 ‘r’(預設) 或 ‘w’。

bufsize – 指明了檔案需要的緩沖大小:0意味着無緩沖;1意味着行緩沖;其它正值表示使用參數大小的緩沖(大概值,以位元組為機關)。負的bufsize意味着使用系統的預設值,一般來說,對于tty裝置,它是行緩沖;對于其它檔案,它是全緩沖。如果沒有改參數,使用系統的預設值。

說明

popen() 建立一個管道,通過fork一個子程序,然後該子程序執行指令。傳回值在标準IO流中,該管道用于父子程序間通信。父程序要麼從管道讀資訊,要麼向管道寫資訊,至于是讀還是寫取決于父程序調用popen時傳遞的參數(w或r)

用法示例

>>> ret = os.popen('ls -a').read()
>>> ret
'.\n..\n.bash_logout\n.bash_profile\n.bashrc\n'
           

将指令執行結果傳回給ret,由于是管道,需要通過read()來擷取内容

3、subprocess 子產品

subprocess 子產品有比較多的功能,這裡隻講用來運作shell指令的幾個方法

subprocess.call()

父程序等待子程序完成

傳回退出資訊(returncode,相當于Linux exit code)

與os.system功能相似

subprocess.check_call()

父程序等待子程序完成

傳回0

檢查退出資訊,如果returncode不為0,則舉出錯誤subprocess.CalledProcessError,該對象包含有returncode屬性,可用try…except…來檢查

subprocess.Popen()

class 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:shell指令,可以是字元串,或者序列類型,如list,tuple。

bufsize:緩沖區大小,可不用關心

stdin,stdout,stderr:分别表示程式的标準輸入,标準輸出及标準錯誤

shell:與上面方法中用法相同

cwd:用于設定子程序的目前目錄

env:用于指定子程序的環境變量。如果env=None,則預設從父程序繼承環境變量

universal_newlines:不同系統的的換行符不同,當該參數設定為true時,則表示使用\n作為換行符

注意:Popen對象建立後,主程式不會自動等待子程序完成。我們必須調用對象的wait()方法,父程序才會等待

不用wait

def no_wait_subprocess():
    child = subprocess.Popen(['ping','-c','4','www.baidu.com'])
    print 'print test'

# 運作結果
print test
[root@]# PING www.a.shifen.com (14.215.177.39) 56(84) bytes of data.
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=1 ttl=55 time=7.56 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=2 ttl=55 time=6.86 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=3 ttl=55 time=8.86 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=4 ttl=55 time=6.74 ms

--- www.a.shifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 6.748/7.510/8.868/0.844 ms

           

使用wait

def wait_subprocess():
    child = subprocess.Popen(['ping','-c','4','blog.csdn.net'])
    child.wait()
    print 'print test'

PING blog.csdn.net (39.96.132.69) 56(84) bytes of data.
64 bytes from 39.96.132.69 (39.96.132.69): icmp_seq=1 ttl=89 time=38.8 ms
64 bytes from 39.96.132.69 (39.96.132.69): icmp_seq=2 ttl=89 time=38.4 ms
64 bytes from 39.96.132.69 (39.96.132.69): icmp_seq=3 ttl=89 time=38.0 ms
64 bytes from 39.96.132.69 (39.96.132.69): icmp_seq=4 ttl=89 time=38.4 ms

--- blog.csdn.net ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2998ms
rtt min/avg/max/mdev = 38.085/38.445/38.827/0.327 ms
print test

           

上面兩個例子對比可以看出有wait的先等popen中指令運作完後再執行下一步

上面的subprocess.Popen運作指令是使用list的方法,也可以使用另一種

subprocess.Popen(‘ping -c 4 blog.csdn.net’,shell=True)

4、commands子產品

commands.getstatusoutput()

擷取傳回狀态和運作結果

用法示例:

>>> (status, output) = commands.getstatusoutput('ls -a')
>>> print status, output
0 .
..
.bash_logout
.bash_profile
.bashrc

           

commands.getoutput()

>>> output = commands.getoutput('ls -a')
>>> print output
.
..
.bash_logout
.bash_profile
.bashrc

           

commands.py源碼分析:

__all__ = ["getstatusoutput","getoutput","getstatus"] #這裡提供了三種方法

# Get 'ls -l' status for an object into a string
#
def getstatus(file):
    """Return output of "ls -ld <file>" in a string."""
    import warnings
    warnings.warn("commands.getstatus() is deprecated", DeprecationWarning, 2)
    return getoutput('ls -ld' + mkarg(file))


# Get the output from a shell command into a string.
# The exit status is ignored; a trailing newline is stripped.
# Assume the command will work with '{ ... ; } 2>&1' around it..
#
def getoutput(cmd):
    """Return output (stdout or stderr) of executing cmd in a shell."""
    return getstatusoutput(cmd)[1]


# Ditto but preserving the exit status.
# Returns a pair (sts, output)
# 這裡是對os.popen的封裝處理
def getstatusoutput(cmd):
    """Return (status, output) of executing cmd in a shell."""
    import os
    pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
    text = pipe.read()
    sts = pipe.close()
    if sts is None: sts = 0
    if text[-1:] == '\n': text = text[:-1]
    return sts, text