2011-10-31 58 views
8

我想在使用子進程模塊的python腳本中使用grep命令。Python子進程Grep

這是我有:

userid = 'foo12' 
p = subprocess.Popen(['grep', "%s *.log"%userid], stdout=subprocess.PIPE) 

而且它沒有返回。 我不完全確定我做錯了什麼,所以有人請解釋。我正在使用的當前方法是通過添加shell = true使其輸出正確的輸出,但由於幫助頁面指出它是不安全的。我需要幫助來完成這項工作,以便我的腳本不是不安全的。

回答

9

我覺得你針對這兩個問題跑起來:

  1. 這一呼籲:

    p = subprocess.Popen(['grep', "%s *.log"%userid]... 
    

    WIL沒有shell=True,因爲參數列表直接傳遞給os.execvp,因此不能按預期工作,這需要每個項目都是代表參數的單個字符串。你已經將兩個單獨的參數一起壓縮成單個字符串(換句話說,grep正在將「foo12 *.log」解釋爲要搜索的模式,而不是模式+文件列表)。

    你可以這樣解決這個問題:

    p = subprocess.Popen(['grep', userid, '*.log']...) 
    
  2. 的第二個問題是,同樣沒有shell=Trueexecvp不知道你*.log的意思,並將其傳遞直接到一起的grep,而無需通過去shell的通配符擴展機制。如果你不希望使用shell=True,可以改爲做這樣的事情:

    import glob 
    args = ['grep', userid] 
    args.extend(glob.glob('*.log') 
    p = subprocess.Popen(args, ...) 
    
7

這裏有兩個測試的代碼段從模型:

>>> print subprocess.check_output(['grep', 'python', 'api_talk.txt']) 
Discuss python API patterns 
Limitations of python 
Introspection in python 

>>> print subprocess.check_output('grep python *.txt', shell=True) 

,如果你想在殼裏做通配符擴展你使用後者。當shellTrue,請務必將整個命令放在一個字符串中,而不是單獨的字段列表中。

4

我假設你希望到grep在與「.LOG」結尾的所有文件「foo12」,得到這個只subprocess工作,你需要將你的代碼更改爲以下:

userid = 'foo12' 
p = subprocess.Popen('grep %s *.log' % userid, stdout=subprocess.PIPE, shell=True) 

shell=True是通配符擴展所必需的,當設置了該選項時,您需要提供一個字符串命令而不是一個列表。

另外,確保當你提供的參數列表中每個參數都在列表中單獨列項,您最初的代碼會一直等同於以下:

grep 'foo12 *.log'