1. 程式人生 > >python subprocess模塊

python subprocess模塊

object 進程 attribute 環境 cte obj callable popen table

subprocess模塊
允許你生成一個或多個進程,並且可以跟它交互,並且獲取返回的結果,這個模塊想要替換掉幾個老的方法:
        os.system
        os.spawn*
        所以以後跟系統交互的命令,盡量用subprocess

建議調用subprocess的run()方法去跟系統進行調用,更高級的方法,使用popen() ;run()方法其實就是封裝的popen。

run()方法在python3.5才有,python2.x沒有,2.x用subprocess.call(),當然python3.X版本也支持call()

常見的subprocess方法

subprocess.call
    subprocess.call("df -lh",shell=True) 或者 subprocess.call(["df","-lh"])
    如果想獲取到執行內容:
         a = subprocess.Popen("df -lh",shell=True,stdout=subprocess.PIPE)
         a.stdout.read()

subprocess.check_call
    執行命令,如果執行狀態碼是 0 ,則返回0,否則拋異常
    subprocess.check_call(["ls","-l"])
    subprocess.check_call("exit 1",shell=True)   拋出異常:subprocess.CalledProcessError:

subprocess.check_output
    執行命令,如果狀態碼是 0 ,則返回執行結果,否則拋異常
    subprocess.check_output(["echo","hello world!"])    返回:‘hello world!\n‘
    subprocess.check_output("exit 1",shell=True)        剖出異常:subprocess.CalledProcessError
    執行命令,並返回結果,註意是返回結果,不是打印,下例結果返回給res
    res = subprocess.getoutput("ls /bin/sh")
    res     輸出:‘/bin/sh‘

subprocess.getstatusoutput
    接收字符串格式命令,返回元組形式,第1個元素是執行狀態,第2個是命令結果
    subprocess.getstatusoutput("ls /bin/ls")        返回:(0, ‘/bin/ls‘)

subprocess.getoutput
    接收字符串格式命令,並返回結果
    subprocess.getoutput("ls /bin/ls")      返回:‘/bin/ls‘

上邊的subprocess方法,底層都是封裝的subprocessPopen

subprocess的其他解說:

poll()
    Check if child process has terminated. Returns returncode
wait()
    Wait for child process to terminate. Returns returncode attribute.

terminate() 殺掉所啟動進程
communicate() 等待任務結束

stdin 標準輸入
stdout 標準輸出
stderr 標準錯誤

pid
    The process ID of the child process.

Popen例子:
    p = subprocess.Popen("df -lh|grep root",stdin=subproce
    p.stdout.read()     輸出:b‘/dev/mapper/cl-root   38G  5.7G   32G  16% /\n‘

run()方法的使用:

    subprocess.run(["ls","-lh"])
    subprocess.run("exit 1",shell=True,check=True)  拋出異常:subprocess.CalledProcessError
    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  3 11:16 /dev/null\n‘)

調用和系統之間的操作,推薦subprocess.run() ,因為它遲早要替換掉sys.system ;
run()方法可以滿足大部分的需求,如果要進行一些復雜的交互的話,還可以用subprocessPopen()
如:
    p = subprocess.Popen("find / -size +1000000 -exec ls -shl {} \;",shell=True,stdout=subprocess.PIPE)
    print (p.stdout.read())
    輸出:b‘0 -r--------. 1 root root 128T Jan 23 14:58 /proc/kcore\n1.9G -rw-------. 1 root root 100G Jan  8 17:48 /var/lib/docker/devicemapper/devicemapper/data\n3.8M -rw-------. 1 root root 2.0G Jan  8 17:48 /var/lib/docker/devicemapper/devicemapper/metadata\n‘

subprocess.Popen(...)

    用於執行復雜的系統命令

    參數:
    args:shell命令,可以是字符串或者序列類型(如:list,元組)
    bufsize:指定緩沖。0 無緩沖,1 行緩沖,其他 緩沖區大小,負值 系統緩沖
    stdin, stdout, stderr:分別表示程序的標準輸入、輸出、錯誤句柄
    preexec_fn:只在Unix平臺下有效,用於指定一個可執行對象(callable object),它將在子進程運行之前被調用
    close_sfs:在windows平臺下,如果close_fds被設置為True,則新創建的子進程將不會繼承父進程的輸入、輸出、錯誤管道。
    所以不能將close_fds設置為True同時重定向子進程的標準輸入、輸出與錯誤(stdin, stdout, stderr)。
    shell:同上
    cwd:用於設置子進程的當前目錄
    env:用於指定子進程的環境變量。如果env = None,子進程的環境變量將從父進程中繼承。
    universal_newlines:不同系統的換行符不同,True -> 同意使用 \n
    startupinfo與createionflags只在windows下有效
    將被傳遞給底層的CreateProcess()函數,用於設置子進程的一些屬性,如:主窗口的外觀,進程的優先級等等

終端輸入的命令分為兩種:
    輸入即可得到輸出:如 ifocnfig
    輸入進行某環境,依賴某環境再輸入:如 python

需要交互的命令示例:
    import subprocess
    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 ‘)  #當從這裏開始就報錯了。
    obj.stdin.write(‘print 4 \n ‘)

    out_error_list = obj.communicate("timeout=10")
    print out_error_list
    輸出:
        (‘‘, ‘  File "<stdin>", line 2\n    print 2 \n    ^\nIndentationError: unexpected indent\n‘)

subprocess實現iptables 清規則的時候 sudo 自動輸入密碼

    import subprocess
    def mypass():
        mypass = ‘123‘  # or get the password from anywhere
        return mypass
    echo = subprocess.Popen([‘echo‘, mypass()],
                            stdout=subprocess.PIPE,
                            )
    sudo = subprocess.Popen([‘sudo‘, ‘-S‘, ‘iptables‘, ‘-L‘],
                            stdin=echo.stdout,
                            stdout=subprocess.PIPE,
                            )
    end_of_pipe = sudo.stdout

    print ("Password ok \n Iptables Chains %s" % end_of_pipe.read())

python subprocess模塊