2017-04-18 43 views
0

我想在我的test.py腳本中運行一個帶有幾個參數的shell命令行。該test.py運行爲:在python中避免shell = True使用命令行參數

python test.py filename file_2 int 

的test.py裏面看起來類似於此:

import sys 

filename = sys.argv[1] 
file_2 = sys.argv[2] 
num = sys.argv[3] 

subprocess.call("xargs /bin/bash build/install/programme/bin/programme option -n "+num+" --csv-file="+str(filename)+" -c files/"+str(file_2)+ "< /tmp/my_ids_"+str(file_2)+"_"+str(num),shell=True) 

的一點是,我使用shell要避免=真,但所有的到目前爲止我發現的選項並不能爲我在命令行中添加的參數提供一個很好的解決方案。

到目前爲止,我已經嘗試通過與Popen拆分它,例如不同的選擇:

import sys 

filename = sys.argv[1] 
file_2 = sys.argv[2] 
num = sys.argv[3] 

subprocess.Popen(["xargs","/bin/bash","build/install/programme/bin/programme","option","-n", str(num),"--csv-file=",str(filename),"-c","files/",str(file_2),"<",str("/tmp/my_ids_"+str(file_2)+"_"+str(num))]) 

但是我沒有工作的結果。還嘗試了shlex,但是在文檔中我再次看不到可以在命令中添加參數的選項。

在此先感謝您的幫助!

+0

爲什麼你想避免'shell = True'? –

+0

@PedroLobito因爲它效率低下並且容易引用錯誤。儘可能將字符串參數列表直接傳遞給'execve'(或正在使用'exec'系列的任何成員)。 – chepner

+0

@PedroLobito,...我會超越「引用錯誤」 - 通過字符串連接生成命令並評估這些字符串,因爲代碼會使您的軟件容易受到注入攻擊。想想[Bobby Tables](https://xkcd.com/327/) - 他有一個名叫'Johnny $(rm -rf $ HOME)'$(rm -rf $ HOME)'的兄弟''。 –

回答

2

你原來的代碼等同於運行以下bash命令:

xargs \ 
    /bin/bash \ 
    build/install/programme/bin/programme \ 
    option \ 
    -n   "$int" \ 
    "--csv-file=" "$filename" \ 
    -c   "files/"   "${file_2}" \ 
    '<'   "/tmp/my_ids_${file_2}_${int}" 

這不會要麼工作,併爲所有同樣的原因。


import sys 

filename = sys.argv[1] 
file_2 = sys.argv[2] 
num = int(sys.argv[3]) 

subprocess.Popen([ 
    "xargs", 
    "/bin/bash", 
    "build/install/programme/bin/programme", 
    "option", 
    "-n", str(num), 
    "--csv-file=%s" % filename, 
    "-c", "files/%s" % file_2, 
], stdin=open("/tmp/my_ids_%s_%s" % (file_2, num), 'r') 

注意區別:

  • 的單個參數總是作爲一個單一的列表成員通過。這意味着--csv-file=filename都是一回事,並且前綴files/和變量file_2中包含的字符串需要在同一個列表元素中傳遞。
  • 重定向(<)是指令到shell,而不是您的程序的參數。因此,您不能在此處使用它們,但應該使用其他選項(如stdinstdout參數Popen)來模擬它們的效果。
  • int是整數類型的名稱;使用變量名稱num保持原始名稱可用。
+0

也許把'int'改成'num',並添加一個關於內置的clobbering的註釋。 –

+0

@DavidCullen,很好的電話。我想了一會兒,但決定放棄它 - 因爲我們在這裏做的是創造一個學習資源,但是,我真的應該花時間在前面解決它。 –

+0

我也改變了原來的帖子,感謝您的建議 – jotNewie