He estado usando argparsepara un programa de Python que puede -process, -uploado 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 argparsepara 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?

-xes universalmente una bandera y opcional. Corta el-si es necesario.processel comportamiento predeterminado (sin la necesidad de especificar ninguna opción) y permitir que el usuario lo cambieuploadsi 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 losargparsedocumentos).Respuestas:
fuente
argparseno 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
--processOR--upload, no XOR. Esto evita que ambas opciones se configuren al mismo tiempo.-xy--xxxson 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.pyPuede 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:
argparseofrece mucho, pero restringe los posibles escenarios y puede volverse muy complejo.Con las
docoptcosas 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 unadocoptbuena 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
--optionbandera connargs="+", la--optionbandera espera al menos un argumento. Si tieneoptionconnargs="+", 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_groupconcepto 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=Truesuficientemente 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'ssimple prueba?fuente
add_usage_groupen 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
--helpmuestra: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
--helpsalida 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