subprocess也是一個(gè)常用的模塊,目前工作所涉及的都比較淺,所以這里只列出一些基本用法和注意點(diǎn)(只適用*nix系統(tǒng))。以后用到advanced的內(nèi)容,會(huì)更新此文章。refer to: python DOC
定義:
spawn新的進(jìn)程,連接input/output/error管道,并獲取錯(cuò)誤碼。
以下模塊不建議繼續(xù)使用,而用subprocess取代:
os.system
os.spawn*
os.popen*
popen2.*
commands.*
subprocess確實(shí)是更加強(qiáng)大,而且以前的模塊有時(shí)候會(huì)有bug。
用法:
-
call:
import subprocess
subprocess.call(["ls", "-l"])
subprocess.call("exit 1", shell=True)
如果只需要獲取子進(jìn)程的錯(cuò)誤碼,這個(gè)方法就足夠了,而且非常好用。
可以看到它有兩種用法,doc里推薦第一種,就是傳一個(gè)字符串list(把cmd split成為一個(gè)list)。第二種呢是直接傳一個(gè)字符串cmd,并把參數(shù)shell賦值為true。
如果用第一種的話,有個(gè)模塊shlex,可以把cmd分解成list,并很好的處理空格和引號(hào)。cmd復(fù)雜的話建議這么使用,不會(huì)出錯(cuò)。
import shlex
command_line = raw_input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
args = shlex.split(command_line)
print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
第二種用法簡單易懂,就不說了??此苾煞N方法都可以,但這里有個(gè)很大的坑:
如果cmd里有管道符,一定要用第二種,否則exit code會(huì)不準(zhǔn)。
具體原因我還沒細(xì)看,童鞋們有精力可以深入研究一下。就是因?yàn)檫@個(gè)坑才讓我重新學(xué)習(xí)這個(gè)模塊,也就有了這篇blog...
-
check_call和check_output:
check_call和call用法基本一樣,唯一的不同點(diǎn)是如果exit code非零,check_call會(huì)raise一個(gè)CalledProcessError。
check_output也是一樣的道理,非零會(huì)raise一個(gè)CalledProcessError。但它return的是output。它還有個(gè)屬性returncode來獲取退出碼。
-
Popen:
最common的方法,可以操作input/output/error管道,并獲得exit code。
Popen和前面的方法有個(gè)很大的不同點(diǎn)是, process會(huì)丟在后臺(tái)運(yùn)行。 而call等方法會(huì)等到proccess運(yùn)行結(jié)束才返回。在使用的時(shí)候要多加注意。
我用一段代碼來說明其用法:
import shlex
from subprocess import Popen, PIPE
def get_exitcode_stdout_stderr(cmd):
"""
Execute the external command and get its exitcode, stdout and stderr.
"""
args = shlex.split(cmd)
proc = Popen(args, stdout=PIPE, stderr=PIPE)
out, err = proc.communicate()
exitcode = proc.returncode
return exitcode, out, err
cmd = "..." # arbitrary external command, e.g. "python mytest.py"
exitcode, out, err = get_exitcode_stdout_stderr(cmd)
應(yīng)該很容易看懂吧。
That's it.