2012-10-02 83 views
1

假設一個python腳本調用具有:使用Python中的命令行參數,而不是外殼

python myscript.py ./mycommand > myoutput.txt 

如何確保myscript.py中的命令行參數的清單得到./mycommand > myoutput.txt而非外殼的管道輸出的python myscript.py ./mycommand的文件?

編輯

使用引號引起了其他問題。試想一下:

import subprocess 
import sys 

argList = sys.argv[1].split() 

subprocess.call(argList) 

然後由稱爲:

python myscript.py 'ls -l > ls.out' 

結果

ls: cannot access >: No such file or directory 
ls: cannot access ls.out: No such file or directory 

的動機是,只能從命令的輸出,我試圖運行應保存在文件。從myscript.pystdout的任何其他輸出都不應該轉到該文件。看起來管道需要設置stdout選項至subprocess.call()。有沒有辦法直接使用參數列表,所以我不必解析它的東西,如>,2>,2&>,<等?

+0

你試過報價了嗎? –

+0

是的,報價將做到這一點,但有沒有辦法做到這一點不引號? – tpg2114

+0

如果不加引號,'> myoutput.txt'不是Python的命令行參數的一部分(在典型的shell中)。 – harpo

回答

2

標準bash或tcsh shell將解析你自己給出的命令,並將某些特殊字符解釋爲shell進程本身的方向(在你的例子中爲「>」字符)。被調用的程序無法控制這個;命令行解析發生在您的程序被調用之前。

在你的榜樣,你可以說:

python myscript.py ./mycommand ">" myoutput.txt 

而援引「>」將告訴shell不要利用其特殊的行爲。

子流程模塊有兩種操作模式;一個帶有外殼(通常是/ bin/sh)的中間過程 - 這是當您將Popen對象設爲shell=True關鍵字參數時。當以這種方式調用它時,它會調用shell來解析參數文本,然後shell會調用您指定爲子進程的命令(一旦從程序中刪除)。

其他操作模式默認爲shell=False。這會創建一個子進程,並直接填充它的ARGV數組,無需任何中間shell試圖解釋命令中的字符。

最終結果是,如果要從解釋特殊字符幷包含特殊字符的shell發出命令,則必須轉義它們或引用它們。如果您正在調用subprocess標準庫模塊的子進程,則可以將任意文本作爲將要進行子進程的ARGV的元素傳遞,而不必擔心它們會由中間shell進程以某種特殊方式進行解釋。

+0

來自這個答案,我不知道你最後一段的意思是...當我做'subprocess.call(「貓foo.txt &&觸摸foo.bar」.split())它假定我'把所有其他的東西都傳遞給貓。所以當你說你可以傳入任意文本作爲子進程的ARGV的元素時,你是不是說你可以傳遞一個任意的shell命令? – 2rs2ts

+0

'subprocess.call(「cat foo.txt && touch foo.bar」.split())'會啓動程序cat並且它的ARGV將被字符串'「foo.txt」,「&&」 ,「touch」,「foo.bar」'。程序'cat'假定位置參數是文件,會被混淆 - 當前目錄中是否有一個名爲'&&「的文件?或者,'subprocess.call(「cat foo.txt && touch foo.bar」,shell = True)'會啓動'/ bin/sh'來解釋命令,而'&&'具有特殊含義如果先前命令已退出代碼0,則評估下一個命令)。 –

+0

謝謝,很高興知道 - 我完全不明白shell的真正含義是什麼,但這很清楚。我如何得到命令的輸出? – 2rs2ts

3

如果你願意承擔依賴,你可以使用Kenneth Reitz's envoy(如果你想從命令行向腳本傳遞任意命令,你仍然需要使用引號)。

from envoy import run 
from sys import argv 

run(argv[1]) 

然後你可以使用調用它:

$ python myscript.py './mycommand > myoutput.txt' 

或者,如果你想在你的Python文件殼狀語法,你可以使用sh(以前pbs)或plumbum

from sh import ls 

with open("myoutput.txt", "w") as outfile: 
    ls("-l", _out=outfile) 

# Or, in plumbum 
from plumbum.cmd import ls 

# Yes, this looks crazy, but the docs say it works. 
ls["-l"] > "myoutput.txt" 
+0

感謝您的鏈接。這些庫非常棒! – 2rs2ts