舉例講解Linux系統下Python調用系統Shell的方法

來源:互聯網
上載者:User
時候難免需要直接調用Shell命令來完成一些比較簡單的操作,比如mount一個檔案系統之類的。那麼我們使用Python如何調用Linux的Shell命令?下面來介紹幾種常用的方法:
1. os 模組

1.1. os模組的exec方法族
Python的exec系統方法同Unix的exec系統調用是一致的。這些方法適用於在子進程中調用外部程式的情況,因為外部程式會替換當前進程的代碼,不會返回。( 這個看了點 help(os) --> search "exec" 的相關介紹,但是沒太搞明白咋使用)


1.2. os模組的system方法
system方法會建立子進程運行外部程式,方法只返回外部程式的運行結果。這個方法比較適用於外部程式沒有輸出結果的情況。

>>> import os >>> os.system("echo \"Hello World\"")  # 直接使用os.system調用一個echo命令 Hello World     ——————> 列印命令結果 0          ——————> What's this ? 傳回值? >>> val = os.system("ls -al | grep \"log\" ")  # 使用val接收傳回值 -rw-r--r-- 1 root    root    6030829 Dec 31 15:14 log  ——————> 此時只列印了命令結果 >>> print val       0          ——————> 注意,此時命令正常運行時,傳回值是0 >>> val = os.system("ls -al | grep \"log1\" ") >>> print val     256         ——————> 使用os.system調用一個沒有返回結果的命令,傳回值為256~ >>>  

注意:上面說了,此方法脂肪會外部程式的結果,也就是os.system的結果,所以如果你想接收命令的傳回值,接著向下看~

1.3. os模組的popen方法
當需要得到外部程式的輸出結果時,本方法非常有用,返回一個類檔案對象,調用該對象的read()或readlines()方法可以讀取輸出內容。比如使用urllib調用Web API時,需要對得到的資料進行處理。os.popen(cmd) 要得到命令的輸出內容,只需再調用下read()或readlines()等 如a=os.popen(cmd).read()

>>> os.popen('ls -lt')         # 調用os.popen(cmd)並不能得到我們想要的結果  >>> print os.popen('ls -lt').read()   # 調用read()方法可以得到命令的結果 total 6064 -rwxr-xr-x 1 long    long      23 Jan 5 21:00 hello.sh -rw-r--r-- 1 long    long      147 Jan 5 20:26 Makefile drwxr-xr-x 3 long    long     4096 Jan 2 19:37 test -rw-r--r-- 1 root    root    6030829 Dec 31 15:14 log drwxr-xr-x 2 long    long     4096 Dec 28 09:36 pip_build_long drwx------ 2 Debian-gdm Debian-gdm  4096 Dec 23 19:08 pulse-gylJ5EL24GU9 drwx------ 2 long    long     4096 Jan 1 1970 orbit-long >>> val = os.popen('ls -lt').read()   # 使用變數可以接收命令傳回值 >>> if "log" in val:          # 我們可以使用in來判斷傳回值中有木有一個字串 ...   print "Haha,there is the log" ... else: ...   print "No,not happy" ... Haha,there is the log 

2. commands 模組

使用commands模組的getoutput方法,這種方法同popend的區別在於popen返回的是一個類檔案對象,而本方法將外部程式的輸出結果當作字串返回,很多情況下用起來要更方便些。
主要方法:
* commands.getstatusoutput(cmd) 返回(status, output)
* commands.getoutput(cmd) 只返回輸出結果
* commands.getstatus(file) 返回ls -ld file的執行結果字串,調用了getoutput,不建議使用此方法

long@zhouyl:/tmp/tests$ python Python 2.7.3 (default, Jan 2 2013, 16:53:07)  [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import commands >>> commands.getstatusoutput('ls -lt')   # 返回(status, output) (0, 'total 5900\n-rwxr-xr-x 1 long long   23 Jan 5 21:34 hello.sh\n-rw-r--r-- 1 long long   147 Jan 5 21:34 Makefile\n-rw-r--r-- 1 long long 6030829 Jan 5 21:34 log') >>> commands.getoutput('ls -lt')      # 返回命令的輸出結果(貌似和Shell命令的輸出格式不同哈~) 'total 5900\n-rwxr-xr-x 1 long long   23 Jan 5 21:34 hello.sh\n-rw-r--r-- 1 long long   147 Jan 5 21:34 Makefile\n-rw-r--r-- 1 long long 6030829 Jan 5 21:34 log' >>> commands.getstatus('log')        # 調用commands.getoutput中的命令對'log'檔案進行相同的操作 '-rw-r--r-- 1 long long 6030829 Jan 5 21:34 log' >>>  

3. subprocess模組

根據Python官方文檔說明,subprocess模組用於取代上面這些模組。有一個用Python實現的並行ssh工具—mssh,代碼很簡短,不過很有意思,它線上程中調用subprocess啟動子進程來幹活。
>>> 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 < input_file | another_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可能更加適合你。

python和shell讀取檔案某一行

python和shell(awk命令) 可以實現直接讀取檔案的某一行,按行號進行讀取 。並可以精準的取得該行的某個欄位,這個有點類似於x軸、y軸定位某個點的操作。

一、awk取某行某列值

awk 可以設定條件來輸出檔案中m行到n行中每行的指定的k欄位,使用格式如下:

awk  'NR==m,NR==n {print $k}' path/filename

m,n,k表示實在的數值。如果要用變數來表示m,n的值,則變數需要用單引號將其引起來。NR,{print }是awk命令在此用法下的規定欄位;path/filename表示讀取檔案的路徑及檔案名稱。這裡指定了兩行,如果只指定一行,可以這樣寫:

awk  'NR==m {print $k}' path/filename

二、python取某行某列

標準庫提供的linecache模組提供具體取某一行的方法:

import linecachetheline = linecache.getline(filepath, line_number)

取到相關的行以後,再對theline做split切分成list,再對list索引取值就行了。如theline.split()[2] 。

三、linecache模組的用法

即然,提到了linecache模組,這裡就列下linecache的其他方法。linecache模組允許從任何檔案裡得到任何的行,並且使用緩衝進行最佳化,常見的情況是從單個檔案讀取多行。

linecache.getlines(filename) 從名為filename的檔案中得到全部內容,輸出為列表格式,以檔案每行為列表中的一個元素,並以linenum-1為元素在列表中的位置儲存
linecache.getline(filename,lineno) 從名為filename的檔案中得到第lineno行。這個函數從不會拋出一個異常–產生錯誤時它將返回”(分行符號將包含在找到的行裡)。如果檔案沒有找到,這個函數將會在sys.path搜尋。
linecache.clearcache() 清除緩衝。如果你不再需要先前從getline()中得到的行
linecache.checkcache(filename) 檢查緩衝的有效性。如果在緩衝中的檔案在硬碟上發生了變化,並且你需要更新版本,使用這個函數。如果省略filename,將檢查緩衝裡的所有條目。
linecache.updatecache(filename) 更新檔案名稱為filename的緩衝。如果filename檔案更新了,使用這個函數可以更新linecache.getlines(filename)返回的列表。
樣本:

# cat a.txt

1a2b3c4d5e6f7g

1、擷取a.txt檔案的內容

>>> a=linecache.getlines('a.txt')>>> a['1a\n', '2b\n', '3c\n', '4d\n', '5e\n', '6f\n', '7g\n']

2、擷取a.txt檔案中第1-4行的內容

>>> a=linecache.getlines('a.txt')[0:4]>>> a['1a\n', '2b\n', '3c\n', '4d\n']

3、擷取a.txt檔案中第4行的內容

>>> a=linecache.getline('a.txt',4)>>> a'4d\n'

注意:

使用linecache.getlines('a.txt')開啟檔案的內容之後,如果a.txt檔案發生了改變,如你再次用linecache.getlines擷取的內容,不是檔案的最新內容,還是之前的內容,此時有兩種方法:

1、使用linecache.checkcache(filename)來更新檔案在硬碟上的緩衝,然後在執行linecache.getlines('a.txt')就可以擷取到a.txt的最新內容;

2、直接使用linecache.updatecache('a.txt'),即可擷取最新的a.txt的最新內容。

讀取檔案之後你不需要使用檔案的緩衝時需要在最後清理一下緩衝,使linecache.clearcache()清理緩衝,釋放緩衝。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.