Как преобразовать аргументы командной строки в python в словарь?

Я пишу приложение, которое принимает аргументы командной строки арбитража, а затем передает их на функцию python:

$ myscript.py --arg1=1 --arg2=foobar --arg1=4 

а затем внутри myscript.py:

 import sys argsdict = some_function(sys.argv) 

где argsdict выглядит так:

 {'arg1': ['1', '4'], 'arg2': 'foobar'} 

Я уверен, что где-то есть библиотека, но я ничего не могу найти.

EDIT: argparse / getopt / optparse – это не то, что я ищу. Эти библиотеки предназначены для определения интерфейса, который является одним и тем же для каждого вызова. Мне нужно иметь возможность обрабатывать произвольные аргументы. Если, argparse / optparse / getopt имеет функциональность, которая делает это …

.. Могу ли я спросить, почему вы пытаетесь переписать (кучу) колеса, когда у вас есть:

?

РЕДАКТИРОВАТЬ:

В ответ на ваше редактирование optparse / argparse (более поздний, доступный только в> = 2.7) достаточно гибкий, чтобы расширяться в соответствии с вашими потребностями, при сохранении согласованного интерфейса (например, пользователь ожидает, что сможет использовать оба --arg=value и --arg value , -a value и -avalue и т. д. с использованием существующей библиотеки, вам не нужно беспокоиться о поддержке всех этих синтаксисов и т. д.).

Что-то вроде этого?

 import sys argsdict = {} for farg in sys.argv: if farg.startswith('--'): (arg,val) = farg.split("=") arg = arg[2:] if arg in argsdict: argsdict[arg].append(val) else: argsdict[arg] = [val] 

Немного отличается от указанного, значение всегда является списком.

Вы можете использовать что-то вроде этого:

myscript.py

 import sys from collections import defaultdict d=defaultdict(list) for k, v in ((k.lstrip('-'), v) for k,v in (a.split('=') for a in sys.argv[1:])): d[k].append(v) print dict(d) 

Результат:

 C:\>python myscript.py --arg1=1 --arg2=foobar --arg1=4 {'arg1': ['1', '4'], 'arg2': ['foobar']} 

Примечание: значение всегда будет списком, но я думаю, что это более согласовано. Если вы действительно хотите, чтобы последний словарь был

 {'arg1': ['1', '4'], 'arg2': 'foobar'} 

то вы могли бы просто запустить

 for k in (k for k in d if len(d[k])==1): d[k] = d[k][0] 

после этого.

Вот пример использования argparse , хотя это растяжка. Я бы не назвал это полное решение, а хорошим началом.

 class StoreInDict(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): d = getattr(namespace, self.dest) for opt in values: k,v = opt.split("=", 1) k = k.lstrip("-") if k in d: d[k].append(v) else: d[k] = [v] setattr(namespace, self.dest, d) # Prevent argparse from trying to distinguish between positional arguments # and optional arguments. Yes, it's a hack. p = argparse.ArgumentParser( prefix_chars=' ' ) # Put all arguments in a single list, and process them with the custom action above, # which convertes each "--key=value" argument to a "(key,value)" tuple and then # merges it into the given dictionary. p.add_argument("options", nargs="*", action=StoreInDict, default=dict()) args = p.parse_args("--arg1=1 --arg2=foo --arg1=4".split()) print args.options 

Это то, что я использовал сегодня, это объясняет:

--key=val , --key , -key , -key val

 def clean_arguments(args): ret_args = defaultdict(list) for index, k in enumerate(args): if index < len(args) - 1: a, b = k, args[index+1] else: a, b = k, None new_key = None # double hyphen, equals if a.startswith('--') and '=' in a: new_key, val = a.split('=') # double hyphen, no equals # single hyphen, no arg elif (a.startswith('--') and '=' not in a) or \ (a.startswith('-') and (not b or b.startswith('-'))): val = True # single hypen, arg elif a.startswith('-') and b and not b.startswith('-'): val = b else: if (b is None) or (a == val): continue else: raise ValueError('Unexpected argument pair: %s, %s' % (a, b)) # santize the key key = (new_key or a).strip(' -') ret_args[key].append(val) return ret_args 

Если вы действительно хотите написать что-то свое, а не надлежащую библиотеку синтаксического анализа командной строки, для вашего ввода это должно работать:

 dict(map(lambda x: x.lstrip('-').split('='),sys.argv[1:])) 

Вам нужно добавить что-то, чтобы ловить аргументы без «=» в них.