[英]Passing a List to Python From Command Line
當提供一些參數時,我想使我的python腳本從命令行運行。 但是,參數之一應該是特定於腳本一個片段的選項列表。 通過從逗號分隔“命令行列表”字符串后實際構造列表,字符串解析是實現此目的的唯一方法嗎? 如果是這樣,您將如何處理?
示例:-details = ['name','title','address']
程序:
import sys, ast, getopt, types
def main(argv):
arg_dict={}
switches={'li':list,'di':dict,'tu':tuple}
singles=''.join([x[0]+':' for x in switches])
long_form=[x+'=' for x in switches]
d={x[0]+':':'--'+x for x in switches}
try:
opts, args = getopt.getopt(argv, singles, long_form)
except getopt.GetoptError:
print "bad arg"
sys.exit(2)
for opt, arg in opts:
if opt[1]+':' in d: o=d[opt[1]+':'][2:]
elif opt in d.values(): o=opt[2:]
else: o =''
print opt, arg,o
if o and arg:
arg_dict[o]=ast.literal_eval(arg)
if not o or not isinstance(arg_dict[o], switches[o]):
print opt, arg, " Error: bad arg"
sys.exit(2)
for e in arg_dict:
print e, arg_dict[e], type(arg_dict[e])
if __name__ == '__main__':
main(sys.argv[1:])
命令行:
python py.py --l='[1,2,3,[1,2,3]]' -d "{1:'one',2:'two',3:'three'}" --tu='(1,2,3)'
輸出:
args: ['--l=[1,2,3,[1,2,3]]', '-d', "{1:'one',2:'two',3:'three'}", '--tu=(1,2,3)']
tu (1, 2, 3) <type 'tuple'>
di {1: 'one', 2: 'two', 3: 'three'} <type 'dict'>
li [1, 2, 3, [1, 2, 3]] <type 'list'>
此代碼段將使用-l
或--li=
類的短命令或長命令開關,並將轉換后的文本解析為Python數據結構(如列表,元組或dict)。 解析的數據結構最終以帶有長格式切換鍵的字典結尾。
使用ast.literal_eval相對安全。 它只能解析python數據定義。
argparse對此很不錯,它在2.7和3.2版本的標准庫中,但不pip install
。
您可以通過使用引號將列表解釋為外殼程序中的單個參數來解決指定可變長度列表的主要問題(可能取決於您的外殼程序,我想):
% python prog.py 'name title address' spam
在哪里prog.py包含
import sys
my_list = sys.argv[1].split()
# my_list is ['name', 'title', 'address']
if 'name' in my_list:
do_something()
或類似。 使用帶有split的參數來分隔列表:
% python prog.py "you're a foo, lift the bar"
my_list = [x.strip() for x in sys.argv[1].split(',')]
# my_list is ["you're a foo", "lift the bar"]
但是請改用argparse; 特別是如果您想使用-c
樣式標志。
一種解釋您的問題的方法是:
“我已經在使用argparse,因為這是解釋Python中命令行參數的明智方法。如何指定某些選項在特定類別內?”
在您的問題中,您顯示了一個示例,說明我使用的外殼會被塞住;
% python prog.py -v -details=['name', 'title', 'address'] --quickly -t 4
不會將其解析為python,因為它們會使用空格分隔參數,並且可能會使用[和]作為shell語法。
我建議以下內容
% python prog.py -v --details name title address --quickly -t 4
其中的prog.py文件
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-v', action='store_true')
parser.add_argument('--details', nargs='*')
parser.add_argument('--quickly', action='store_true')
parser.add_argument('-t')
args = parser.parse_args()
#args is Namespace(details=['asdf', 'a', 'a'], quickly=False, t='4', v=True)
details = args.details
#details is ['asdf', 'a', 'a']
現在,根據您的問題,您不必自己解析字符串。
是的, argparse是最好的選擇,如果您想為您的一個命名參數提供值列表,它看起來像這樣( nargs
參數是實現此目的的關鍵):
>>> import argparse
>>> arg_parser = argparse.ArgumentParser()
>>> arg_parser.add_argument('--details',
nargs='*',
type=str,
default=[],
help='a list of the details')
# your args on the command line like this example
>>> the_args = arg_parser.parse_args("--details 'name' 'title' 'address'".split())
>>> print the_args.details
["'name'", "'title'", "'address'"])
我真的很喜歡the-wolf的使用可變長度集合作為顯式字符串參數的方法。
在我看來, nargs='*'
有一個值得注意的缺點:當嘗試將字符串作為位置參數收集時(必須存在至少一個字符串),或者如果您嘗試使用子解析器,您會發現nargs='*'
和nargs='+'
使用貪婪nargs='+'
,並且它們似乎並沒有因為任何很好的原因而停止消耗。 即使出現可選參數或數字的語法,string()類型也將繼續使用。 (分包商很難預測到這一點)。
最好的情況是,放在(位置和可選)之后的參數將被忽略,更糟糕的是,您可能會將損壞的數據類型傳遞給argparse數組。
我們應該能夠定義一個自定義的ActionType來查找帶引號的字符串。 如果找到一個,則我們改編the-wolf的示例(似乎幾乎逐字記錄)。
這使argparse中的內容保持整潔,並使變量集合的一般用法不太麻煩。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.