Analizar Argumentos CLI: argparse, Commander y picocli
Cómo analizar argumentos de línea de comandos en aplicaciones CLI de Python, Java y Node.js.
Visión General
El análisis de argumentos de línea de comandos es lo primero que ven los usuarios al ejecutar tu herramienta. Una buena
CLI expone flags claros, opciones tipadas, texto de ayuda automático y subcomandos que se sienten como git push o
docker run.
Cuándo Usar
Usá esto cuando construyas herramientas de desarrollo, scripts de build, automatización de deployment o pipelines de datos que necesiten entradas configurables. También sirve para interfaces basadas en subcomandos o cuando hard-codear valores haría que un script sea más difícil de reutilizar.
Requisitos Previos
- Python: 3.8+ para
argparse(librería estándar).Clickrequierepip install click.typerrequierepip install typer. - Node.js: 16+ para
commander(imports ESM). Instalá connpm install commander.yargses una alternativa (npm install yargs). - Java: 8+ para
picocli. Agregá la dependencia Maveninfo.picocli:picocli:4.7.6o la equivalente de Gradle.
Solución
Python
# argparse es la librería estándar para CLI en Python
import argparse
parser = argparse.ArgumentParser(description='Procesar archivos.')
parser.add_argument('input', help='Ruta del archivo de entrada')
parser.add_argument('-o', '--output', default='out.txt', help='Ruta del archivo de salida')
parser.add_argument('-v', '--verbose', action='store_true', help='Activar logging detallado')
args = parser.parse_args()
print(f'Input: {args.input}, Output: {args.output}, Verbose: {args.verbose}')
# Click es una alternativa popular de terceros
# pip install click
import click
@click.command()
@click.argument('input')
@click.option('--output', '-o', default='out.txt', help='Archivo de salida')
@click.option('--verbose', '-v', is_flag=True, help='Modo detallado')
def cli(input, output, verbose):
click.echo(f'Input: {input}, Output: {output}, Verbose: {verbose}')
if __name__ == '__main__':
cli()
# Subcomandos con argparse (como git push / git pull)
import argparse
parser = argparse.ArgumentParser(prog='mytool')
sub = parser.add_subparsers(dest='command', required=True)
# subcomando push
push = sub.add_parser('push', help='Enviar datos al remoto')
push.add_argument('--force', action='store_true', help='Forzar envío')
# subcomando pull
pull = sub.add_parser('pull', help='Bajar datos del remoto')
pull.add_argument('--depth', type=int, default=1, help='Profundidad de clonado')
args = parser.parse_args()
print(f'Comando: {args.command}, Force: {getattr(args, "force", False)}')
JavaScript
// process.argv integrado de Node.js es el array raw
const args = process.argv.slice(2);
console.log(args);
// Commander.js es el framework CLI más popular para Node.js
// npm install commander
import { Command } from 'commander';
const program = new Command();
program
.argument('<input>', 'Ruta del archivo de entrada')
.option('-o, --output <file>', 'Ruta del archivo de salida', 'out.txt')
.option('-v, --verbose', 'Activar logging detallado')
.action((input, options) => {
console.log(`Input: ${input}, Output: ${options.output}, Verbose: ${options.verbose}`);
});
program.parse();
Java
// picocli es el estándar moderno para CLI en Java
// Maven: info.picocli:picocli
import picocli.CommandLine;
import picocli.CommandLine.Parameters;
import picocli.CommandLine.Option;
import java.util.concurrent.Callable;
@CommandLine.Command(name = "process", mixinStandardHelpOptions = true)
public class ProcessFile implements Callable<Integer> {
@Parameters(index = "0", description = "Ruta del archivo de entrada")
private String input;
@Option(names = {"-o", "--output"}, defaultValue = "out.txt")
private String output;
@Option(names = {"-v", "--verbose"})
private boolean verbose;
@Override
public Integer call() {
System.out.printf("Input: %s, Output: %s, Verbose: %b%n", input, output, verbose);
return 0;
}
public static void main(String[] args) {
int exitCode = new CommandLine(new ProcessFile()).execute(args);
System.exit(exitCode);
}
}
Explicación
Los frameworks CLI toman el array de argumentos raw (sys.argv, process.argv o String[] args) y lo convierten en
valores tipados. Generan automáticamente texto de ayuda, validan argumentos requeridos y convierten valores como
--count 5 a enteros. También se encargan de flags booleanos, argumentos posicionales, inputs variádicos y subcomandos.
argparse de Python viene con la librería estándar y cubre la mayoría de los scripts. Click usa decoradores y es más
fácil de componer. En JavaScript, commander es la opción más común, con configuración encadenable. picocli usa
anotaciones de Java y funciona bien con compilación a native-image de GraalVM para CLIs de arranque rápido.
Un patrón común es combinar argumentos CLI con archivos de configuración. Por ejemplo, una herramienta puede aceptar un
flag --config que apunta a un archivo YAML o TOML, y luego sobrescribir valores del archivo con flags de línea de
comandos. Ver Parsear Archivos YAML en Python y JavaScript y
Parsear Archivos TOML en Python y Java para ejemplos de lectura de config files que
combinan bien con parsing CLI.
Si tu CLI procesa entrada estructurada, puede que también quieras validarla contra un schema antes de ejecutar. Mirá Validar JSON Schema en Python y JavaScript para patrones de validación de schema que funcionan junto al parsing de argumentos.
Variantes
| Tecnología | Librería | Enfoque | Notas |
|---|---|---|---|
| Python | argparse | Librería estándar | Cero dependencias, ayuda auto-generada |
| Python | Click | Decoradores | Componible, soporta barras de progreso y prompts |
| Python | typer | Type hints | Construido sobre Click, usa anotaciones Python 3.6+ |
| JavaScript | commander | API Fluent | Más popular, soporta subcomandos |
| JavaScript | yargs | Cadena middleware | Altamente extensible, bueno para CLIs complejos |
| Java | picocli | Anotaciones | Scripts de autocompletado, soporte native-image |
| Java | Apache Commons CLI | Patrón Builder | Más antiguo pero ampliamente usado en enterprise |
Buenas Prácticas
Usá librerías estándar primero (argparse, process.argv) para scripts simples y evitar bloat de dependencias. Agregá
flags -h y --help a toda CLI, porque los frameworks generan esto automáticamente. Validá argumentos requeridos temprano
y mostrá mensajes amigables, no stack traces.
Soportá --version para que usuarios y pipelines de CI/CD puedan fijar versiones de herramientas. Salí con código 0 en
caso de éxito y uno distinto de cero ante fallas, así los shell scripts pueden detectar cuando algo falló.
Errores Comunes
Parsear process.argv manualmente en lugar de usar un framework conduce a código frágil y no mantenible. Cuando faltan
argumentos requeridos, los usuarios deberían ver el texto de ayuda, no un stack trace.
Mutar estado global en handlers de CLI dificulta el testing y la composición. Ignorar códigos de salida significa que los
pipelines de CI/CD no pueden detectar fallas si la CLI siempre sale con 0. Sobre-ingenieriar subcomandos también es
común: un script simple con flags suele ser más simple que una CLI multinivel.
Cuándo No Usar
Si un script solo necesita una entrada fija, una CLI es innecesaria; usá una función o una variable de entorno. Si una herramienta solo la ejecutan otros scripts, un archivo de configuración o variables de entorno pueden ser más limpios que flags. Para hot paths críticos en rendimiento donde el overhead del parsing importe, considerá opciones pre-parseadas o compiladas.
Resumen
- Usá
argparsepara scripts Python sin dependencias; pasá aClickcuando necesites composición y decoradores. commanderes la opción estándar para CLIs de Node.js, conyargscomo alternativa más extensible.picoclies el estándar moderno de Java, con config basada en anotaciones y soporte native-image de GraalVM.- Siempre agregá flags
--helpy--version; los frameworks los generan automáticamente. - Salí con
0en éxito y distinto de cero en fallos para que los pipelines de CI/CD detecten problemas. - Combiná flags CLI con archivos de config (YAML, TOML) para herramientas que necesiten config persistente o compleja.
- Código companion completo con tests: stack-practices-resources.
See Also
- Documentación de Python argparse — Referencia oficial del parser de la librería estándar.
- Documentación de Commander.js — Framework CLI para Node.js con API fluent y soporte de subcomandos.
- Documentación de picocli — Framework CLI para Java con anotaciones, autocompletado y soporte native-image.
- Documentación de Click — Framework CLI para Python con decoradores y comandos componibles.
- 12 Factor CLI Apps — Principios para construir CLIs mantenibles que funcionen bien en containers y CI.
Preguntas frecuentes
¿Cómo manejo variables de entorno junto con argumentos CLI?
Usá librerías que soporten fallbacks de variables de entorno. Click expone envvar= y picocli expone
defaultValue = "${ENV_VAR}". Las variables de entorno son ideales para secretos y valores específicos de deployment que
no deberían aparecer en el historial de shell.
¿Cuál es la mejor forma de testear aplicaciones CLI?
Invocá el punto de entrada de la CLI como una función en lugar de spawnear subprocesos. Click de Python tiene
runner.invoke(), picocli tiene CommandLine.execute() in-process, y commander se puede testear llamando a
.parse() con un array argv simulado. Eso es mucho más rápido que testing basado en shell.
¿Cómo construyo una CLI con subcomandos?
Todos los frameworks principales soportan subcomandos. En argparse, usá add_subparsers(). En commander, llamá a
.command() para cada subcomando. En picocli, anotá clases anidadas con @Command. Poné las opciones compartidas en
una clase padre o mixin para evitar duplicación.
¿Cómo valido tipos de argumentos más allá de lo que ofrece el framework?
argparse soporta type=int o callables custom. Click usa click.IntRange o subclasses custom de ParamType.
commander acepta una función de parse como tercer argumento de .option(). picocli usa @Option(type=...) con
implementaciones de ITypeConverter built-in o custom. Validá temprano y fallá con un mensaje de error claro.
¿Qué códigos de salida debería usar?
Seguí la convención POSIX: 0 para éxito, 1 para errores generales, 2 para errores de parsing de argumentos.
argparse sale con 2 por defecto en fallos de parse. picocli retorna el valor de call() como exit code.
commander setea process.exitCode en lugar de llamar process.exit() directamente, lo que deja que los handlers
async terminen primero.
¿Cómo agrego autocomplete a mi CLI?
argparse no soporta autocomplete nativamente, pero argcomplete lo agrega con un solo decorador. Click genera
scripts de completion vía click.completion. commander soporta completion con el plugin commander-completion.
picocli genera scripts de completion con picocli.AutoComplete.
Recursos Relacionados
Analizar Archivos YAML
Cómo analizar archivos de configuración YAML en Python, Java y JavaScript.
RecipeAnalizar TOML: Python, Java y JS con Ejemplos
Cómo analizar y escribir archivos de configuración TOML en Python, Java y JavaScript.
RecipeValidar JSON Schema
Cómo validar datos JSON contra schemas en Python, Java y JavaScript.
RecipeAnalizar Archivos CSV
Cómo analizar archivos CSV en Python, Java y JavaScript con ejemplos de código prácticos.
RecipeParsear JSON
Cómo parsear cadenas JSON a estructuras de datos nativas en varios lenguajes de programación.
RecipeAnalizar archivos de log con Python, Java y JavaScript
Cómo analizar archivos de log de servidores con Python, Java y JavaScript. Incluye regex, logs estructurados, seguimiento en tiempo real y seguridad.