有時候難免需要直接呼叫Shell指令來完成一些比較簡單的操作,像是mount一個檔案系統之類的。那我們使用Python如何呼叫Linux的Shell指令?以下來介紹幾個常用的方法:
1. os 模組
1.1. os模組的exec方法族
Python的exec系統方法同Unix的exec系統呼叫是一致的。這些方法適用 於在子進程中呼叫外部程式的情況,因為外部程式會取代目前進程的程式碼,不會回傳。 ( 這個看了點help(os) --> search "exec" 的相關介紹,但是沒太搞明白咋使用)
1.2. os模組的system方法
system方法會創建子進程運行外部程式,方法只傳回外部程式的運行結果。這個方法比較適用於外部程式沒有輸出結果的情況。
[python] view plaincopy
>>> import os
>>> os.system("echo "Hello World ————— —> 列印指令結果
0 ----> What's this ??
>>> val = os.system("ls -al | grep "log" ") # 使用val接收回值
9 Dec 31 15:14 log — —————> 此時只列印了指令結果 >>> print val 0 是0 >>> val = os.system("ls -al | grep "log1" ") >>> print val 呼叫一個沒有回傳結果的指令,回傳值為256~>>>
注意:上面說了,此方法脂肪會外部程序的結果,也就是os.system的結果,所以如果你想接收命令的回傳值,接著向下看~
1.33 . os模組的popen方法
drwxr-xr-x 3 long long 4096 Jan 2 19:37 testo 6030829 Dec 31 15:14 log
drwxr-xr-x 2 long long 2 long 09:36 pip_build_long
drwx------ 2 Debian-gdm Debian-gdm 4096 Dec 23 19:08 pulsese-GUdr123 . long 4096 Jan 1 1970 orbit-long
>>> val = os.popen('ls -lt').read() # 使用變數使用in來判斷回傳值中有木有一個字串
... print "Haha,there is the log"
... else:
Haha,there is the log 2. commands 模組使用commands模組的getoutput方法,此方法是同popend的區別在於popen
使用commands模組的getoutput方法,此方法將外部程式輸出的區別在於popen」是一個類別檔案作字串返回,很多情況下用起來要更方便。主要方法:
* commands.getstatusoutput(cmd) 返回(status, output)
[python] view plaincopy
Type "help", "copyright", "credits" or "license" for more information. statusoutput('ls -lt ') # 返回(status, output)
(0, 'total 5900n-rwxr-xr-x 1 long long long long 147 Jan 5 21:34 Makefilen-rw-r--r-- 1 long long 6030829 Jan 5 21:34 log')
>>結果(貌似和Shell指令的輸出格式不同哈~)
'total 5900n-rwxr-xr-x 1 long long 23 Jan 5 21:34 hello.shn-143 Jan 5 21:34 Makefilen -rw-r--r-- 1 long long 6030829 Jan 5 21:34 log'
>>>進行相同的操作
'-rw-r--r-- 1 long long 6030829 Jan 5 21:34 log'
>>> 官方文件說明,subprocess模組用於取代上面這些模組。有一個用Python實現的平行ssh工具—mssh,程式碼很簡短,不過很有意思,它在執行緒中呼叫subprocess啟動子程序來工作。
[python] view plaincopy>>> from subprocess import call>>> call(["ls", "-l"])
subprocess與system相比的優點是它更靈活(你可以得到標準輸出,標準錯誤,「真正」的狀態碼,更好的錯誤處理,等..)。我認為使用os.system已過時,或即將過時。
4. 眾方法的比較以及總結
4.1. 關於os.system
os.system("some_command with args")將命令以及參數傳遞給你的系統shell,這很好,因為你可以用這種方法同時運行多個命令並且可以設定管道以及輸入輸出重定向。例如:
os.system("some_command output_file")
然而,雖然這很方便,但是你需要手動處理shell字元的轉義,例如空格等。此外,這也只能讓你執行簡單的shell指令而且不能執行外部程式。
4.2. 關於os.popen
使用stream = os.popen("some_command with args")也能做與os.system一樣的事,與os.system不同的是os.popen會回傳一個類文件對象,使用它來存取標準輸入、輸出。
4.3. 關於subprocess.popen
subprocess模組的Popen類,意圖作為os.popen的替代,但是因為其很全面所以比os.popen要顯得稍微複雜。
例如你可以用 print Popen("echo Hello World", stdout=PIPE, shell=True).stdout.read() 來取代 print os.popen("echo Hello World").read()。但相較之下它使用一個統一的類別包括4中不同的popen函數還是不錯的。
4.4. 關於subprocess.call
subprocess模組的call函數。它基本上就像Popen類別並且都使用相同的參數,但是它只簡單的等待命令完成並給你返回程式碼。例如:
return_code = subprocess.call("echo Hello World", shell=True)
os模組中還有C中那樣的fork/exec/spawn函數,但是我不建議直接使用它們。 subprocess可能更適合你。
===========================================
[1] http://demi-panda.com/2013/01/25/python-shell-command/index.html
[2] http://m.blog.csdn.net/blog/overstack/9295995
[3] http://blog.csdn.net/swiftshow/article/details/7755543
下面是文中所涉及的內容的python官方文件:
[4] http://docs.python.org/library/subprocess .html#replacing-older-functions-with-the-subprocess-module -- 關於使用subprocess 替代舊的方法
[5] http://docs.python.org/lib/os-process.html --os的exec方法族以及system方法
[6] http://docs.python.org/lib/os-newstreams.html -- os的popen方法
[7] http://docs.python.org/ lib/node528.html -- os的subprocess介紹