python subprocess


  運行python的時候,我們都是在創建並運行一個進程。像Linux進程那樣,一個進程可以fork一個子進程,並讓這個子進程exec另外一個程序。在Python中,我們通過標准庫中的subprocess包來fork一個子進程,並運行一個外部的程序。
  subprocess包中定義有數個創建子進程的函數,這些函數分別以不同的方式創建子進程,所以我們可以根據需要來從中選取一個使用。另外subprocess還提供了一些管理標准流(standard stream)和管道(pipe)的工具,從而在進程間使用文本通信。

 

call(*popenargs, **kwargs): 執行命令,返回狀態碼

>>> import subprocess
>>> ret = subprocess.call(["ls", "-l"])
total 216
-rw-r--r-- 1 root root   297 May  5 21:23 class.py
-rw-r--r-- 1 root root   330 May  4 10:33 fenye.py
-rw-r--r-- 1 root root   173 May  4 07:24 obj.py
>>> ret = subprocess.call("ls -l")   #默認shell=False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  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 1308, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
>>> ret = subprocess.call("ls -l", shell=True)   #shell=True不會報錯
total 216
-rw-r--r-- 1 root root   297 May  5 21:23 class.py
-rw-r--r-- 1 root root   330 May  4 10:33 fenye.py
-rw-r--r-- 1 root root   173 May  4 07:24 obj.py
>>> print(ret)
0

 

check_call(*popenargs, **kwargs): 執行命令,如果執行狀態碼是 0 ,則返回0,否則拋異常

>>> ret = subprocess.call(["cd", "A"])
/usr/bin/cd: line 2: cd: A: No such file or directory
>>> ret = subprocess.check_call(["cd", "A"])
/usr/bin/cd: line 2: cd: A: No such file or directory
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 542, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['cd', 'A']' returned non-zero exit status 1

 

check_output(*popenargs, **kwargs):執行命令,如果狀態碼是 0 ,則返回執行結果,否則拋異常

>>> ret = subprocess.check_output(["ls", "-l"])
>>> print(ret)
total 216
-rw-r--r-- 1 root root   297 May  5 21:23 class.py
-rw-r--r-- 1 root root   330 May  4 10:33 fenye.py
-rw-r--r-- 1 root root   173 May  4 07:24 obj.py
>>> ret = subprocess.check_output(["lsa", "-l"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 568, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1308, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

 

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()函數,用於設置子進程的一些屬性,如:主窗口的外觀,進程的優先級等等 
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
>>> obj.stdin.write("print('hello')\n")
>>> obj.stdin.write("print('hello word')")
>>> obj.stdin.close()
>>> cmd_out = obj.stdout.read()
>>> obj.stdout.close()
>>> cmd_error = obj.stderr.read()
>>> obj.stderr.close()
>>> print(cmd_out)
hello
hello word

>>> print(cmd_error)

或者

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> obj.stdin.write("print('hello word')")
>>> out_error_list = obj.communicate()
>>> print(out_error_list)
('hello word\n', '')

管道(shell中的|)

[root@Python ~]# ls -l | wc -l
18
>>> p1=subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
>>> p2=subprocess.Popen(["wc","-l"], stdin=p1.stdout,stdout=subprocess.PIPE)
>>> out=p2.communicate()
>>> print(out)
(b'18\n', None)

上面實例其執行過程:

child1.stdout-->subprocess.PIPE

child2.stdin<--subprocess.PIPE

child2.stdout-->subprocess.PIPE

需要注意的是:communicate()是Popen對象的一個方法,該方法會阻塞父進程,直到子進程完成


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM