He estado usando argparse
para un programa de Python que puede -process
, -upload
o ambos:
parser = argparse.ArgumentParser(description='Log archiver arguments.')
parser.add_argument('-process', action='store_true')
parser.add_argument('-upload', action='store_true')
args = parser.parse_args()
El programa no tiene sentido sin al menos un parámetro. ¿Cómo puedo configurar argparse
para forzar la elección de al menos un parámetro?
ACTUALIZAR:
Siguiendo los comentarios: ¿Cuál es la forma Pythonic de parametrizar un programa con al menos una opción?
-x
es universalmente una bandera y opcional. Corta el-
si es necesario.process
el comportamiento predeterminado (sin la necesidad de especificar ninguna opción) y permitir que el usuario lo cambieupload
si esa opción está configurada? Por lo general, las opciones deben ser opcionales, de ahí el nombre. Deben evitarse las opciones obligatorias (esto también se encuentra en losargparse
documentos).Respuestas:
fuente
argparse
no tiene una opción incorporada para esto.fuente
vars()
, que también es útil para pasar opciones cuidadosamente nombradas a un constructor con **.vars
. Simplemente lo hice.__dict__
y me sentí tonto antes.Si no es la parte 'o ambas' (inicialmente me perdí esto), podría usar algo como esto:
Sin embargo, probablemente sería una mejor idea usar subcomandos en su lugar.
fuente
--process
OR--upload
, no XOR. Esto evita que ambas opciones se configuren al mismo tiempo.-x
y--xxx
son típicamente parámetros opcionales.Sé que esto es viejo como la suciedad, pero la forma de requerir una opción pero prohibir más de una (XOR) es así:
Salida:
fuente
Revisión de requisitos
argparse
(ignoraré este)También hay algunos requisitos implícitos cuando se vive en la línea de comandos:
Solución de muestra usando
docopt
(archivomanagelog.py
):Intenta ejecutarlo:
Muestre la ayuda:
Y úsalo:
Alternativa corta
short.py
Puede haber una variante incluso más corta:
El uso se ve así:
Tenga en cuenta que, en lugar de valores booleanos para las claves de "proceso" y "carga", hay contadores.
Resulta que no podemos evitar la duplicación de estas palabras:
Conclusiones
En ocasiones, diseñar una buena interfaz de línea de comandos puede ser un desafío.
Hay varios aspectos del programa basado en la línea de comandos:
argparse
ofrece mucho, pero restringe los posibles escenarios y puede volverse muy complejo.Con las
docopt
cosas van mucho más cortas conservando la legibilidad y ofreciendo un alto grado de flexibilidad. Si logra obtener argumentos analizados del diccionario y realiza algunas conversiones (a números enteros, abrir archivos ...) manualmente (o mediante otra biblioteca llamadaschema
), puede encontrar unadocopt
buena opción para el análisis de línea de comandos.fuente
Si necesita que un programa de Python se ejecute con al menos un parámetro, agregue un argumento que no tenga el prefijo de opción (- o - por defecto) y establezca
nargs=+
(Se requiere un mínimo de un argumento). El problema que encontré con este método es que si no especificas el argumento, argparse generará un error de "muy pocos argumentos" y no imprimirá el menú de ayuda. Si no necesita esa funcionalidad, aquí se explica cómo hacerlo en el código:Yo creo que cuando se agrega una discusión con los prefijos de opción, nargs gobierna todo el analizador argumento y no sólo la opción. (Lo que quiero decir es que, si tiene una
--option
bandera connargs="+"
, la--option
bandera espera al menos un argumento. Si tieneoption
connargs="+"
, espera al menos un argumento en general).fuente
choices=['process','upload']
a ese argumento.Para http://bugs.python.org/issue11588 , estoy explorando formas de generalizar el
mutually_exclusive_group
concepto para manejar casos como este.Con este desarrollo
argparse.py
, https://github.com/hpaulj/argparse_issues/blob/nested/argparse.py puedo escribir:que produce lo siguiente
help
:Esto acepta entradas como '-u', '-up', '--proc --up', etc.
Termina ejecutando una prueba similar a https://stackoverflow.com/a/6723066/901925 , aunque el mensaje de error debe ser más claro:
Me pregunto:
¿Son los parámetros lo
kind='any', required=True
suficientemente claros (acepte cualquiera del grupo; se requiere al menos uno)?¿Está
(-p | -u)
claro el uso ? Un grupo mutually_exclusive_group requerido produce lo mismo. ¿Existe alguna notación alternativa?¿Usar un grupo como este es más intuitivo que una
phihag's
simple prueba?fuente
add_usage_group
en esta página: docs.python.org/2/library/argparse.html ; ¿Podría proporcionar un enlace a la documentación correspondiente?La mejor manera de hacer esto es usando el módulo incorporado de Python add_mutually_exclusive_group .
Si desea que solo se seleccione un argumento mediante la línea de comando, use required = True como argumento para el grupo
fuente
¿Quizás usar sub-analizadores?
Ahora
--help
muestra:También puede agregar opciones adicionales a estos sub-analizadores. Además, en lugar de usar eso
dest='subparser_name'
, también puede vincular funciones para que se invoquen directamente en un subcomando dado (ver documentos).fuente
Esto logra el propósito y esto también se verá afectado en la
--help
salida autogenerada de argparse , que es en mi humilde opinión lo que quieren la mayoría de los programadores cuerdos (también funciona con argumentos opcionales):Documentos oficiales sobre esto: https://docs.python.org/3/library/argparse.html#choices
fuente
Use append_const para una lista de acciones y luego verifique que la lista esté completa:
Incluso puede especificar los métodos directamente dentro de las constantes.
fuente