Est-il possible d'aller chercher plusieurs valeurs pour une option à l'aide de GetOPT ou OPTPARSE, comme indiqué dans l'exemple ci-dessous:
./hello_world -c arg1 arg2 arg3 -b arg4 arg5 arg6 arg7
Veuillez noter que le nombre de valeurs réelles pour chaque option (-C, -b) pourrait être 1 ou 100. Je ne veux pas utiliser: ./hello_world -c "arg1 arg2 arg3" -b "arg4 arg5 arg6 arg7"
Il me semble que cela peut ne pas être possible (et peut-être en violation de POSIX), veuillez me corriger si je me trompe.
J'ai vu des exemples où toutes les non-options à la fin de la ligne (./hello_world -c arg1 -b arg1 arg2 arg3
) Peut être rassemblé ... mais pas pour la première option multiple.
J'aimerais que mon application fonctionne sur une large gamme de plates-formes avec différents Python versions, donc je n'ai pas regardé Argpararser.
Oui, cela peut être fait avec OptParse.
Ceci est un exemple:
./test.py --categories=aaa --categories=bbb --categories ccc arg1 arg2 arg3
qui imprime:
arguments: ['arg1', 'arg2', 'arg3']
options: {'categories': ['aaa', 'bbb', 'ccc']}
Exemple de travail complet ci-dessous:
#!/usr/bin/env python
import os, sys
from optparse import OptionParser
from optparse import Option, OptionValueError
VERSION = '0.9.4'
class MultipleOption(Option):
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
values.ensure_value(dest, []).append(value)
else:
Option.take_action(self, action, dest, opt, value, values, parser)
def main():
PROG = os.path.basename(os.path.splitext(__file__)[0])
long_commands = ('categories')
short_commands = {'cat':'categories'}
description = """Just a test"""
parser = OptionParser(option_class=MultipleOption,
usage='usage: %prog [OPTIONS] COMMAND [BLOG_FILE]',
version='%s %s' % (PROG, VERSION),
description=description)
parser.add_option('-c', '--categories',
action="extend", type="string",
dest='categories',
metavar='CATEGORIES',
help='comma separated list of post categories')
if len(sys.argv) == 1:
parser.parse_args(['--help'])
OPTIONS, args = parser.parse_args()
print "arguments:", args
print "options:", OPTIONS
if __name__ == '__main__':
main()
Plus d'informations sur http://docs.python.org/library/optparse.html#adding-new-actions
Malgré les revendications des autres commentaires, cela est possible avec Vanilla OptParse, au moins comme de python 2.7. Vous devez simplement utiliser action = "APPEND". Du docs :
parser.add_option("-t", "--tracks", action="append", type="int")
Si -T3 est vu sur la ligne de commande, OPTPARSE fait l'équivalent de:
options.tracks = []
options.tracks.append(int("3"))
Si, un peu plus tard, --Tracks = 4 est vu, il fait:
options.tracks.append(int("4"))
Vous pouvez le faire avec le paramètre nargs
dans argparse
qui est livré avec Python2.7 et téléchargeable ici .
Je pense que c'est l'une des améliorations ajoutées à argparse
qui n'est pas dans optparse
. Donc, malheureusement, je ne pense pas qu'il y a une bonne façon de gérer cela avec optparse
ou getopt
(qui est encore plus âgé).
Une solution rapide et sale pourrait être de renoncer à optparse/getop/argparse
et juste analyser sys.argv
toi-même.
Ou, dans la direction opposée, vous pourriez envisager d'emballer une copie gelée de Argparse (~ 88K) (renommé quelque chose comme argparse_static
) Avec votre programme et l'important comme ceci:
try:
import argparse
except ImportError:
import argparse_static as argparse
De cette façon, le programme utilisera argparse
s'il est installé et utilisera argparse_static
si ce n'est pas le cas. Le meilleur de tous, vous n'aurez pas à réécrire beaucoup de code comme argparse
devient standard.
Ni getopt ni optParse ne le soutiennent hors de la boîte. De plus, dans le mode par défaut (GNU), les arguments supplémentaires seraient traités comme des arguments disperpersés, c'est-à-dire disponibles en tant qu'arguments de gauche à la fin du traitement.
La convention serait d'exiger une mention répétée du même argument, c'est-à-dire.
./hello_world -c arg1 -c arg2 -c arg3 -b arg4 -b arg5 -b arg6 -b arg7
Ceci est soutenu.
Si vous voulez absolument le faire fonctionner, votre façon de spécifier (c'est-à-dire -b et -c étendre jusqu'au prochain argument ou à la fin de la liste des arguments), vous pouvez alors pirater quelque chose en fonction de l'optparse. Hériter d'OptionParser et remplacer _process_short_opts. Si c'est une de vos options, traitez-la dans la sous-classe, sinon vers la classe de base.
Une autre option serait de définir un séparateur et de le traiter localement, comme les options de la commande de montage.
Par exemple, si ,
peut être utilisé comme séparateur:
...
args, _ = getopt.getopt(sys.argv[1:],'b:')
for flag, arg in args:
if flag=='-b': all_arguments = arg.split(',')
...
$ ./test -b opt1,opt2,opt3
Idem pour l'espace! Mais alors vos utilisateurs doivent le citer correctement.
$ ./test -b 'opt1 opt2 opt3'