2014-08-27 33 views
3

我有以下代碼,用於從文件中讀取參數並使用argparse處理它們,但出現錯誤,爲什麼會出現這種情況?Argparse中的異常

import argparse 
from ConfigParser import ConfigParser 
import shlex 

parser = argparse.ArgumentParser(description='Short sample app', 
           fromfile_prefix_chars='@') 

parser.add_argument('--abool', action="store_true", default=False) 
parser.add_argument('--bunit', action="store", dest="bunit",type=int) 
parser.add_argument('--cpath', action="store", dest="c", type=str) 

print parser.parse_args(['@argparse_fromfile_prefix_chars.txt']) #name of the file is argparse_fromfile_prefix_chars.txt 

錯誤:文件

usage: -c [-h] [--abool] [--bunit BUNIT] [--cpath C] 
-c: error: unrecognized arguments: --bunit 289 --cpath /path/to/file.txt 
To exit: use 'exit', 'quit', or Ctrl-D. 

內容argparse_fromfile_prefix_chars.txt

--abool 
--bunit 289 
--cpath /path/to/file.txt 

回答

1

​​預計從文件的參數是每行一個。意味着整條線是一個引用的論點。因此,您當前的參數文件被解釋爲

python a.py '--abool' '--bunit 289' '--cpath /path/to/file.txt' 

這會導致錯誤。相反,你的ARGS文件應該是這樣的

--abool 
--bunit 
289 
--cpath 
/path/to/file.txt 
+2

或者他的文件可能有這三行:'--abool','--bunit = 289','--cpath =/path/to/file.txt'。 – 2014-08-27 21:05:57

+0

我這樣做,我仍然得到相同的錯誤 – Lanc 2014-08-27 21:30:34

+0

@Robᵩ建議爲我工作....謝謝:) – Lanc 2014-08-27 21:32:56

1

的文檔fromfile_prefix_chars狀態:

Arguments read from a file must by default be one per line (but see also convert_arg_line_to_args()) and are treated as if they were in the same place as the original file referencing argument on the command line.

注意一個參數意味着一個選項後面的所有參數。它意味着一個命令行參數。目前整條線被解釋爲它們是單個參數。

換句話說,你的文件應該是這樣的:

--abool 
--bunit 
289 
--cpath 
/path/to/file.txt 

或者你可以重寫convert_arg_line_to_args()方法來解析該文件中的其他方式。該文件已經提供瞭解析空格分隔的參數,而不是線分隔參數的實現:即使設置屬性上的ArgumentParser

def convert_arg_line_to_args(self, arg_line): 
    # consider using shlex.split() instead of arg_line.split() 
    for arg in arg_line.split(): 
     if not arg.strip(): 
      continue 
     yield arg 

我相信你既可以子類ArgumentParser並重新實​​現此方法,或者,也許,實例應該工作。不過,如果你使用上面的執行它的工作原理

$echo '--abool   
--bunit 
289 
--cpath 
/here/is/a/path 
' > file.txt 
$cat test_argparse.py 
import argparse 

parser = argparse.ArgumentParser(fromfile_prefix_chars='@') 
parser.add_argument('--abool', action='store_true') 
parser.add_argument('--bunit', type=int) 
parser.add_argument('--cpath') 


print(parser.parse_args(['@file.txt'])) 
$python test_argparse.py 
usage: test_argparse.py [-h] [--abool] [--bunit BUNIT] [--cpath CPATH] 
test_argparse.py: error: unrecognized arguments: 


出於某種原因的convert_arg_line_to_args默認實現不能正常工作

$cat test_argparse.py  
import argparse 

def convert_arg_line_to_args(arg_line): 
    for arg in arg_line.split(): 
     if not arg.strip(): 
      continue 
     yield arg.strip() 

parser = argparse.ArgumentParser(fromfile_prefix_chars='@') 
parser.add_argument('--abool', action='store_true') 
parser.add_argument('--bunit', type=int) 
parser.add_argument('--cpath') 
parser.convert_arg_line_to_args = convert_arg_line_to_args 

print(parser.parse_args(['@file.txt'])) 
$python test_argparse.py 
Namespace(abool=True, bunit=289, cpath='/here/is/a/path') 

的其他解決方法是使用--option=argument語法:

--abool 
--bunit=289 
--cpath=/the/path/to/file.txt 

但是,當一個選項有多個參數時,這不起作用。在這種情況下,您必須使用convert_arg_line_to_args的不同實現。


嘗試調試,這似乎是convert_line_arg_to_args被調用與被添加到參數空字符串,空字符串被認爲是一個參數(不定義)。

問題是在文件末尾有兩個換行符。 如果您在最後沒有這雙新行創建文件實際上,它的工作原理:

$echo -n '--abool 
--bunit 
289 
--cpath 
/here/is/a/path 
' > file.txt 
$python test_argparse.py 
Namespace(abool=True, bunit=289, cpath='/here/is/a/path') 

echo -n不會在輸出的末尾添加一個新行)。

+0

我做到了,我仍然得到相同的錯誤 – Lanc 2014-08-27 21:31:01

+0

What @Robᵩ建議爲我工作 – Lanc 2014-08-27 21:33:20

+0

@Lanc出於某種原因,'convert_arg_line_to_args'的默認實現無法正常工作。如果你在我的答案中使用了示例實現,它就可以工作。 – Bakuriu 2014-08-28 06:12:39