---
title: "Argparse em Python: Guia Completo com Exemplos Práticos"
url: "https://python.dev.br/blog/argparse-python-guia-completo/"
markdown_url: "https://python.dev.br/blog/argparse-python-guia-completo.MD"
description: "Aprenda a usar o argparse em Python: argumentos posicionais e opcionais, flags, subcomandos, tipos, nargs, validação e boas práticas. Guia completo com exemplos."
date: "2026-07-03"
author: "Equipe Python Brasil"
---

# Argparse em Python: Guia Completo com Exemplos Práticos

Aprenda a usar o argparse em Python: argumentos posicionais e opcionais, flags, subcomandos, tipos, nargs, validação e boas práticas. Guia completo com exemplos.


O **argparse** é o módulo da biblioteca padrão do Python dedicado a criar interfaces de linha de comando (CLI). Com ele, você transforma um script simples em uma ferramenta profissional que aceita argumentos posicionais, flags, subcomandos, valida entradas e gera mensagens de ajuda automáticas — tudo sem instalar nenhuma dependência extra. Se você está começando agora, vale ler primeiro o [Como Começar com Python](/blog/como-comecar-com-python/); aqui o foco é colocar a mão na massa no terminal.

Para quem só quer uma definição rápida, temos a entrada de [argparse no glossário](/glossario/argparse/). Neste guia completo, vamos do primeiro exemplo a subcomandos, validação customizada e boas práticas. Se o objetivo é comparar bibliotecas de CLI inteiras (argparse, Typer, Click e uv), confira o [guia de CLI com Python](/blog/criando-cli-com-python/) — aqui mergulhamos fundo só no argparse, que é a base de todas elas.

## Por que usar o argparse

Antes do argparse, muitos scripts Python lidavam com argumentos lendo `sys.argv` manualmente — frágil, repetitivo e propenso a erros. O argparse resolve três problemas de uma vez:

1. **Define o que o programa aceita**: argumentos posicionais, flags, tipos e valores permitidos.
2. **Gera ajuda e uso automaticamente**: o `--help` sai de graça, sempre atualizado.
3. **Valida e converte entradas**: erros de tipo ou valor viram mensagens claras, não exceções obscuras.

Como faz parte da biblioteca padrão, o argparse está disponível em qualquer instalação de Python a partir da versão 3.2 — não há nada para instalar com [gerenciadores de pacotes](/blog/gerenciadores-de-pacotes-python/) como o [uv](/blog/uv-gerenciador-pacotes-python/). É só importar e usar.

## Primeiro exemplo: uma CLI em 10 linhas

Vamos criar uma ferramenta que processa um arquivo de texto e aceita um formato de saída. Salve como `processa.py`:

```python
import argparse

parser = argparse.ArgumentParser(
    description="Processa um arquivo de texto e imprime o resultado.",
)

# Argumento posicional (obrigatório)
parser.add_argument("arquivo", help="Caminho do arquivo de entrada")

# Argumento opcional (flag com valor padrão)
parser.add_argument(
    "-f", "--formato",
    choices=["txt", "csv", "json"],
    default="txt",
    help="Formato de saída (padrão: txt)",
)

# Flag booleana
parser.add_argument("-v", "--verbose", action="store_true", help="Modo detalhado")

args = parser.parse_args()

print(f"Arquivo: {args.arquivo}")
print(f"Formato: {args.formato}")
print(f"Verbose: {args.verbose}")
```

Rode `python processa.py dados.txt --formato csv -v` e verá:

```text
Arquivo: dados.txt
Formato: csv
Verbose: True
```

Experimente `python processa.py -h`. O argparse monta a ajuda sozinho, listando o argumento `arquivo`, a flag `--formato` (com as opções aceitas) e a flag `--verbose`. É difícil exagerar o quanto isso economiza tempo quando a CLI cresce.

## Argumentos posicionais e opcionais

A diferença entre os dois é o prefixo do nome:

- **Posicional** (`"arquivo"`): obrigatório, definido pela ordem em que aparece. Bom para a entrada principal do comando.
- **Opcional** (`"-f"`, `"--formato"`): começa com `-` (curto) ou `--` (longo). Pode ter valor padrão e geralmente não é obrigatório.

```python
parser.add_argument("origem", help="Arquivo de origem")        # posicional
parser.add_argument("-o", "--saida", help="Arquivo de saída")   # opcional
```

Se um argumento posicional faltar, o argparse encerra com erro e mostra o uso — você não precisa escrever essa lógica.

## Tipos, valores permitidos e defaults

O parâmetro `type` converte a entrada; `choices` restringe os valores; `default` define o valor quando o argumento não aparece:

```python
parser.add_argument("--porta", type=int, default=8000, help="Porta do servidor")
parser.add_argument("--nivel", choices=["debug", "info", "erro"], default="info")
parser.add_argument("--taxa", type=float, default=0.5, help="Taxa de processamento")
```

Assim, `--porta abc` vira um erro claro em vez de um `int()` quebrado no meio da execução. Para datas e outros formatos, basta passar uma [função](/glossario/funcao/) que faça a conversão (veremos isso na seção de validação).

## Flags booleanas e a armadilha do `type=bool`

Para ligar/desligar um comportamento, use `action`:

```python
parser.add_argument("--verbose", action="store_true", help="Liga o modo detalhado")
parser.add_argument("--silencioso", action="store_false", dest="verbose")
```

- `action="store_true"` → `False` por padrão, `True` quando a flag aparece.
- `action="store_false"` → o oposto (útil para uma flag `--nao-verbose`).
- `action="count"` → conta repetições (`-vvv` vira `3`), ótimo para níveis de verbosidade.
- `action="append"` → acumula valores repetidos em uma lista (`--tag a --tag b` → `["a", "b"]`).

**Armadilha clássica:** `type=bool` não funciona. `--ativo=False` ainda vira `True`, porque `bool("False")` é `True` (string não vazia). Para booleanos, sempre use `action`.

## Aceitando múltiplos valores com `nargs`

O `nargs` controla quantos valores um argumento consome:

```python
parser.add_argument("--arquivos", nargs="+", help="Um ou mais arquivos")
parser.add_argument("--dimensoes", nargs=2, type=int, metavar=("LARGURA", "ALTURA"))
parser.add_argument("--log", nargs="?", const="app.log", default=None,
                    help="Sem valor usa app.log; ausente fica None")
```

- `nargs="+"` → um ou mais valores (lista).
- `nargs="*"` → zero ou mais (lista, pode ser vazia).
- `nargs="?"` → valor opcional; `const` é usado quando a flag aparece sem valor.
- `nargs=2` → exatamente dois valores.

O resultado chega sempre como lista quando `nargs` é `+`, `*` ou um número.

## Subcomandos com `add_subparsers`

Ferramentas como `git` usam subcomandos (`git commit`, `git push`). O argparse faz isso com `add_subparsers`:

```python
import argparse

parser = argparse.ArgumentParser(prog="dbcli", description="Gerencia um banco de dados")
sub = parser.add_subparsers(dest="comando", required=True, help="Comandos disponíveis")

# subcomando: criar
p_criar = sub.add_parser("criar", help="Cria um novo banco")
p_criar.add_argument("nome", help="Nome do banco")
p_criar.add_argument("--tipo", choices=["sqlite", "postgres"], default="sqlite")

# subcomando: backup
p_backup = sub.add_parser("backup", help="Faz backup do banco")
p_backup.add_argument("destino", help="Diretório de destino")
p_backup.add_argument("--compactar", action="store_true")

args = parser.parse_args()

if args.comando == "criar":
    print(f"Criando banco {args.nome} ({args.tipo})")
elif args.comando == "backup":
    print(f"Backup para {args.destino} (compactar={args.compactar})")
```

Agora `python dbcli.py criar loja --tipo postgres` e `python dbcli.py backup /tmp` funcionam como comandos separados, cada um com a própria ajuda. O padrão `set_defaults(func=...)` é uma forma elegante de despachar para a função certa sem uma cadeia de `if`.

## Mensagens de ajuda personalizadas

Quatro parâmetros deixam a ajuda profissional:

```python
parser = argparse.ArgumentParser(
    prog="logtools",
    description="Analisa arquivos de log de aplicação.",
    epilog="Exemplo: logtools analisar app.log --nivel erro",
    formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument("--version", action="version", version="%(prog)s 1.0.0")
```

- `prog` → nome do programa na ajuda (útil quando o nome do arquivo não é o que o usuário digita).
- `description` e `epilog` → texto no topo e no rodapé da ajuda.
- `formatter_class=argparse.RawDescriptionHelpFormatter` → preserva quebras de linha no `epilog` (caso você queira listar exemplos).
- `action="version"` → imprime a versão e sai.

## Grupos mutuamente exclusivos e organização

Para flags que não fazem sentido juntas (`--json` **ou** `--csv`, nunca ambos):

```python
grupo = parser.add_mutually_exclusive_group()
grupo.add_argument("--json", action="store_true", help="Saída em JSON")
grupo.add_argument("--csv", action="store_true", help="Saída em CSV")
```

E para organizar a ajuda em seções lógicas, use `add_argument_group`:

```python
srv = parser.add_argument_group("opções do servidor")
srv.add_argument("--host", default="localhost")
srv.add_argument("--porta", type=int, default=8000)
```

## Validação customizada com `type`

O `type` aceita qualquer função que receba uma string e devolva o valor convertido — ou levante `argparse.ArgumentTypeError`. Isso centraliza a validação:

```python
import argparse
from pathlib import Path

def arquivo_existente(caminho: str) -> Path:
    p = Path(caminho)
    if not p.is_file():
        raise argparse.ArgumentTypeError(f"Arquivo não encontrado: {caminho}")
    return p

def porta_valida(valor: str) -> int:
    porta = int(valor)
    if not (1 <= porta <= 65535):
        raise argparse.ArgumentTypeError("A porta deve estar entre 1 e 65535")
    return porta

parser = argparse.ArgumentParser()
parser.add_argument("entrada", type=arquivo_existente)
parser.add_argument("--porta", type=porta_valida, default=8000)

args = parser.parse_args()
print(f"Lendo: {args.entrada} | porta: {args.porta}")
```

A mensagem de erro aparece formatada como uso incorreto, mantendo a CLI consistente. Combinado com [type hints](/blog/tipagem-estatica-python-mypy/), o código fica legível e seguro.

## Erros comuns

- **Confundir posicional com opcional**: esquecer o `--` transforma uma flag em obrigatório e quebra o uso.
- **`type=bool`**: não use para flags; prefira `action="store_true"`/`"store_false"`.
- **`nargs="*"` vazio**: aceita zero valores e devolve uma lista vazia — trate esse caso antes de iterar.
- **Subcomando ausente**: sem `required=True` (ou `dest`) em `add_subparsers`, o atributo pode não existir e causa `AttributeError`. Defina `dest` e valide antes de acessar.
- **Ajuda genérica**: strings de `help` vagas tornam a CLI difícil. Descreva o que cada argumento faz e o valor padrão.

## Boas práticas

- Sempre passe `description` no parser e `help` em cada argumento.
- Use `choices` para restringir valores e evitar validação manual.
- Centralize conversões complexas em funções de `type` reutilizáveis.
- Adicione `--version` e um `--verbose` como padrão em ferramentas sérias.
- Quebre CLIs grandes em subcomandos em vez de uma única lista longa de flags.
- Escreva exemplos no `epilog` — usuários copiam exemplos muito mais do que leem a ajuda inteira.

Para ferramentas que vão crescer muito, vale considerar Typer ou Click, mas entender o argparse primeiro torna qualquer migração trivial, porque os conceitos (argumentos, flags, subcomandos, ajuda) são os mesmos.

## Testando uma CLI de argparse

CLIs merecem testes. O truque é chamar `parse_args` passando uma lista de argumentos, sem depender do `sys.argv` real:

```python
def test_formato_padrao():
    args = parser.parse_args(["dados.txt"])
    assert args.formato == "txt"
    assert args.verbose is False

def test_flag_verbose():
    args = parser.parse_args(["dados.txt", "-v"])
    assert args.verbose is True
```

Esse padrão roda direto com [pytest](/guias/testes-com-pytest/) e deixa a CLI segura para refatorar. Se você usa [Ruff](/blog/ruff-linter-formatador-python/) para lint e formatação, a integração com testes é imediata.

## Perguntas frequentes

### O argparse exige instalação?

Não. O argparse faz parte da biblioteca padrão do Python desde a versão 3.2, então basta `import argparse` — não é preciso `pip install` nem nada do [uv](/blog/uv-gerenciador-pacotes-python/).

### Como fazer `--formato` aceitar só alguns valores?

Use `choices`: `parser.add_argument("--formato", choices=["txt", "csv", "json"], default="txt")`. Qualquer valor fora da lista vira erro automático com mensagem de uso.

### Argparse conta como projeto de portfólio?

Sim. Uma CLI pequena com testes, README, tratamento de erro e exemplos mostra automação prática e maturidade — ótimo para um [portfólio Python](/carreira/projetos-portfolio-python/) e para processos de [vagas](/vagas/). Combine com subcomandos e validação e ela se destaca mais que um script solto.

## Próximos passos

Você agora tem o argparse suficiente para construir CLIs profissionais sem dependências. Para evoluir:

- Compare com Typer e Click no [guia de CLI com Python](/blog/criando-cli-com-python/).
- Aprofunde tipagem com o guia de [mypy e tipagem estática](/blog/tipagem-estatica-python-mypy/).
- Trate dados de entrada com [expressões regulares](/blog/expressoes-regulares-python/) e [funções](/glossario/funcao/) de validação.

Dominar o argparse é um desses fundamentos que aparecem em quase toda vaga Python — vale o investimento.
