Trilha de aprendizado · Nível 15 · Tutorial 5

Traduzir falhas em mensagens e códigos de saída

Estabelecer um contrato de sucesso e falha para a CLI, separando resultados, mensagens ao usuário e informações de diagnóstico.

  • Nível: Intermediário
  • Duração: 15 min
  • 7 passos
Traduzir falhas em mensagens e códigos de saída

O que você vai percorrer

  1. Separe resultados de mensagens de erro Use stdout para o resultado da operação e stderr para erros e diagnósticos, mesmo que ambos apareçam no mesmo terminal. 2 min
  2. Defina o contrato de códigos de saída Use códigos de saída para que pessoas e outros programas interpretem o resultado de uma execução de forma coerente. 2 min
  3. Respeite as saídas do argparse Preveja o comportamento padrão do argparse para ajuda, argumentos inválidos e chamadas válidas. 2 min
  4. Concentre o encerramento no ponto de entrada Organize a CLI para que main retorne códigos e o ponto de entrada encerre o processo. 2 min
  5. Traduza falhas conhecidas em orientações úteis Converta falhas previstas da operação em mensagens claras para o usuário, mantendo stderr e o código de saída contratados. 3 min
  6. Preserve o diagnóstico de falhas inesperadas Diferencie defeitos inesperados de falhas previstas e preserve evidências úteis para investigação. 2 min
  7. Aplique e confira o contrato completo Execute uma CLI autocontida em seis cenários e compare canais, mensagens, diagnóstico e código de saída. 3 min

O que você vai aprender

  • Encaminhar resultados para a saída padrão e mensagens de erro para a saída de erro.
  • Definir códigos de saída coerentes para sucesso, uso incorreto e falhas esperadas.
  • Converter exceções conhecidas em mensagens que indiquem uma ação possível ao usuário.
  • Preservar evidências de defeitos inesperados sem apresentá-los como operações bem-sucedidas.

Antes de começar

  • Carregar configurações externas com precedência explícita
  • Criar exceções para erros do domínio
  • Registrar eventos e exceções com logging

Passo 1 de 7

Separe resultados de mensagens de erro

Use stdout para o resultado da operação e stderr para erros e diagnósticos, mesmo que ambos apareçam no mesmo terminal.

Dois canais, duas funções

Resultado não é diagnóstico

Uma CLI tem dois canais de texto importantes. Use stdout para o resultado que a pessoa ou outro programa quer consumir. Use stderr para mensagens de erro e diagnósticos.

Separar os canais permite, por exemplo, guardar somente o resultado em um arquivo sem misturar avisos ou explicações técnicas.

Fluxo de uma execução

A tela do terminal pode mostrar ambos os textos juntos, mas eles continuam em canais separados.

Diagrama mostrando uma CLI enviando um resultado para stdout e uma mensagem de erro para stderr; os dois fluxos chegam visualmente ao mesmo terminal.

Mesmo terminal visível não significa o mesmo canal de saída.

Escrevendo no canal de erro

Use file=sys.stderr

Por padrão, print() escreve em stdout. Para enviar uma mensagem a stderr, importe sys e passe file=sys.stderr.

O resultado abaixo permanece limpo em stdout; a mensagem sobre o problema segue separadamente para stderr.

Dois prints, dois destinos

python
import sys

print("Registro encontrado: Ana")
print("Aviso: o cadastro está desatualizado.", file=sys.stderr)

Escolha o canal adequado

Associe cada conteúdo ao canal

Relacione cada exemplo ao canal mais adequado.

Toque em um item e depois no par correspondente.

Passo 2 de 7

Defina o contrato de códigos de saída

Use códigos de saída para que pessoas e outros programas interpretem o resultado de uma execução de forma coerente.

Mensagem e código cumprem papéis diferentes

Dois sinais para o resultado

Uma CLI comunica o desfecho por dois meios complementares:

  • Mensagem: explica a situação para uma pessoa.
  • Código de saída: permite que um script, um shell ou outra ferramenta reconheça se a execução deu certo.

Por convenção, 0 significa sucesso. Qualquer valor diferente de zero indica falha. O destino da mensagem e o código são decisões independentes: imprimir em stderr não altera automaticamente o código de saída.

Canais e status são independentes

A mensagem pode seguir para stdout ou stderr; o status é um sinal separado enviado ao término da execução.

Diagrama com uma CLI no centro: uma seta leva mensagens de resultado a stdout, outra leva erros a stderr, e uma terceira leva um número de status ao shell.

Uma execução pode escrever em stderr e, ainda assim, informar status 0 se o programa não definir um status de falha.

Contrato adotado nesta CLI

Uma tabela simples e explícita

Neste exemplo, a aplicação adota este contrato:

| Código | Categoria |
|---:|---|
| 0 | sucesso ou solicitação de ajuda |
| 2 | uso incorreto dos argumentos |
| 3 | falha esperada da operação, como configuração inválida ou registro ausente |
| 1 | defeito inesperado que precisa de investigação |

Os valores não zero não são uma classificação universal do Python. Eles fazem parte do contrato desta aplicação; documente-os e aplique-os de modo consistente.

Exemplo

Mesmo texto, sinais diferentes

Considere estas duas execuções conceituais:

stderr: Erro: registro "A-17" não encontrado.
status: 0
stderr: Erro: registro "A-17" não encontrado. Verifique o identificador e tente novamente.
status: 3

A segunda é coerente: a pessoa recebe orientação em stderr, e a automação recebe o sinal de falha esperada (3). A primeira mostra um erro, mas comunica sucesso incorretamente.

Aplique o contrato

Escolha o status adequado

A CLI recebeu argumentos válidos, mas o identificador solicitado não existe. Qual código ela deve sinalizar segundo o contrato deste tutorial?

Detecte a incoerência

Erro exibido, sucesso sinalizado

Uma execução produz o seguinte resultado:

stderr: Configuração inválida: informe uma porta entre 1 e 65535.
status: 0

Qual é o problema?

Passo 3 de 7

Respeite as saídas do argparse

Preveja o comportamento padrão do argparse para ajuda, argumentos inválidos e chamadas válidas.

Três resultados possíveis antes da operação

O parser também encerra execuções

Depois de receber os argumentos, o argparse pode concluir a execução antes de sua operação começar.

  • --help: mostra a ajuda em stdout e encerra com código 0.
  • Argumentos inválidos: mostra uso e erro em stderr e encerra com código 2.
  • Argumentos válidos: entrega os valores interpretados para que a operação continue.

Portanto, pedir ajuda é um caminho bem-sucedido de consulta da interface, não uma falha.

Fluxos do parser

Compare o canal, o código e a continuidade de cada chamada.

Diagrama com três fluxos de uma CLI: ajuda vai para stdout e termina com código zero; argumento inválido vai para stderr e termina com código dois; argumento válido segue para a operação.

A operação só é alcançada quando os argumentos passam pela validação do parser.

Observe sem depender do texto exato

Uma CLI mínima

Salve este exemplo como consulta.py para observar os três caminhos.

python
import argparse


def criar_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="Consulta um registro.")
    parser.add_argument("registro_id", type=int)
    return parser


def consultar(registro_id: int) -> None:
    print(f"Registro consultado: {registro_id}")


def main(argv: list[str] | None = None) -> None:
    argumentos = criar_parser().parse_args(argv)
    consultar(argumentos.registro_id)


if __name__ == "__main__":
    main()

Exemplo

O que esperar em cada chamada

python consulta.py --help
→ ajuda em stdout; código 0; consultar() não é chamada

python consulta.py abc
→ uso e erro em stderr; código 2; consultar() não é chamada

python consulta.py 42
→ "Registro consultado: 42" em stdout; consultar() é chamada

A redação e a formatação da ajuda e do erro podem variar. O contrato importante aqui é canal, código e se a operação foi iniciada.

Dica

Separe duas categorias de falha

Um argumento rejeitado pelo parser é um erro de uso da CLI. Uma falha descoberta depois de consultar(...) começar pertence à operação e terá seu próprio tratamento nos próximos passos.

Faça a previsão

Ajuda é sucesso

Na chamada python consulta.py --help, o argparse deve escrever a ajuda em stdout, encerrar com código 0 e não chamar consultar.

Argumento rejeitado

Para python consulta.py abc, qual previsão respeita o comportamento padrão do argparse?

Passo 4 de 7

Concentre o encerramento no ponto de entrada

Organize a CLI para que main retorne códigos e o ponto de entrada encerre o processo.

Retorne o resultado do fluxo

main decide; a borda encerra

Faça main receber argv opcional e retornar um inteiro quando seu fluxo termina normalmente. Esse inteiro representa o resultado da execução conforme o contrato da CLI.

Porém, return 0 apenas devolve um valor para quem chamou main; ele não encerra o processo com código zero por conta própria.

Retorno não é encerramento

A separação permite testar e reutilizar main sem que ela finalize o processo durante a chamada.

Diagrama mostrando argumentos entrando em main, main retornando o número zero ao ponto de entrada e o ponto de entrada encerrando o processo.

main retorna o código; a fronteira externa transforma esse retorno no encerramento do processo.

Transforme o retorno em código do processo

Estrutura da entrada da CLI

O bloco protegido executa somente quando este arquivo é iniciado diretamente.

python
import argparse


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser()
    parser.add_argument("nome")
    return parser


def main(argv: list[str] | None = None) -> int:
    args = build_parser().parse_args(argv)
    print(f"Olá, {args.nome}!")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

Dica

Uma fronteira pequena e explícita

raise SystemExit(main()) fica no ponto de entrada. Assim, as funções que executam regras da aplicação retornam resultados ou sinalizam suas próprias falhas, sem decidir quando o processo inteiro deve terminar.

Não engula o encerramento do parser

argparse pode encerrar antes do return

Ao interpretar argv, o argparse pode levantar SystemExit: por exemplo, para ajuda (--help) ou argumentos inválidos. Nesse caso, main não chega ao seu return.

SystemExit deriva de BaseException, e não de Exception. Portanto, except Exception não intercepta esse encerramento — e isso é desejável.

Atenção

Evite capturas amplas demais

Não use except: nem except BaseException: em volta de parse_args() ou de toda a CLI. Essas capturas podem engolir o SystemExit do argparse e impedir os códigos e comportamentos esperados de ajuda e erro de uso.

Complete a ligação

No ponto de entrada, use raise ______(main()) para encerrar o processo com o inteiro retornado por main.

Confira a separação

Qual captura preserva o comportamento do argparse?

Se uma seção posterior da CLI precisar tratar exceções comuns da aplicação, qual opção não captura o SystemExit que o argparse pode levantar?

Passo 5 de 7

Traduza falhas conhecidas em orientações úteis

Converta falhas previstas da operação em mensagens claras para o usuário, mantendo stderr e o código de saída contratados.

Traduza na fronteira da CLI

Exceção interna, orientação externa

A CLI é a fronteira que conhece tanto a configuração quanto o caso de uso. É nela que uma falha prevista pelo contrato pode ser convertida em uma orientação para quem executou o comando.

Capture tipos específicos, como ConfiguracaoInvalida e RegistroNaoEncontrado. Não use except ValueError apenas porque uma falha poderia envolver um valor: um ValueError pode ter outra origem e não é automaticamente um erro de uso da CLI.

Para cada falha esperada deste exemplo: escreva a mensagem em stderr, não imprima resultado em stdout e retorne 3.

Da falha prevista à resposta da CLI

Diagrama mostrando duas exceções conhecidas, configuração inválida e registro não encontrado, chegando à fronteira da CLI e sendo transformadas em mensagens de erro no stderr e código de saída 3; a saída de sucesso stdout permanece sem conteúdo.

A exceção conhecida não atravessa a interface sem tradução: ela vira uma mensagem acionável em stderr e o retorno 3.

Dica

Contexto útil e seguro

Inclua apenas o contexto necessário para agir: a chave de configuração inválida ou o identificador solicitado. Não despeje o conteúdo completo da configuração, credenciais, tokens ou detalhes internos que não ajudam na correção.

Capture somente o que a operação prevê

Tratamento específico em main

As classes representam falhas já previstas pelo domínio e pela configuração. A função main as traduz para a interface de linha de comando.

python
import sys


class ConfiguracaoInvalida(Exception):
    def __init__(self, chave: str):
        self.chave = chave


class RegistroNaoEncontrado(Exception):
    def __init__(self, identificador: str):
        self.identificador = identificador


def carregar_configuracao() -> dict[str, str]:
    # Exemplo: a validação anterior detectou uma chave inválida.
    raise ConfiguracaoInvalida("diretorio_dados")


def consultar_registro(identificador: str, config: dict[str, str]) -> str:
    raise RegistroNaoEncontrado(identificador)


def main(argv: list[str] | None = None) -> int:
    identificador = "A-104"  # Viria dos argumentos já interpretados.

    try:
        config = carregar_configuracao()
        resultado = consultar_registro(identificador, config)
    except ConfiguracaoInvalida as erro:
        print(
            f"Erro de configuração: revise o valor de '{erro.chave}' e execute novamente.",
            file=sys.stderr,
        )
        return 3
    except RegistroNaoEncontrado as erro:
        print(
            f"Registro '{erro.identificador}' não foi encontrado. "
            "Confirme o identificador e tente novamente.",
            file=sys.stderr,
        )
        return 3

    print(resultado)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

Exemplo

Compare três mensagens

Vaga: Erro.

Técnica demais: RegistroNaoEncontrado: A-104 em repositorio._indice[identificador]

Adequada: Registro 'A-104' não foi encontrado. Confirme o identificador e tente novamente.

A última explica o problema, preserva o contexto necessário e oferece uma próxima ação. Ela não expõe a implementação interna.

Atenção

Não anuncie sucesso

Se uma dessas exceções for capturada, encerre aquele caminho com return 3. Não imprima uma confirmação de sucesso antes nem depois do tratamento da falha.

Projete a tradução de uma falha

Mensagem, canal e retorno

Um usuário solicitou o registro C-77, e o caso de uso levantou RegistroNaoEncontrado. Descreva onde você capturaria essa exceção e escreva a mensagem. Indique também o canal e o código de retorno. Evite detalhes internos e não use uma captura genérica de ValueError.

Escreva pelo menos 120 caracteres (0/120).

Passo 6 de 7

Preserve o diagnóstico de falhas inesperadas

Diferencie defeitos inesperados de falhas previstas e preserve evidências úteis para investigação.

Defeito não é erro de entrada

Duas respostas para duas situações

Uma falha prevista — como configuração inválida ou registro inexistente — já tem uma mensagem e retorno próprios. Um defeito inesperado é diferente: indica algo que precisa ser investigado.

Na fronteira da CLI, mantenha as capturas específicas primeiro. Depois delas, uma captura final de Exception pode informar a falha sem fingir que o problema foi causado pelo argumento do usuário.

Mensagem e evidência têm papéis distintos

O usuário precisa de uma orientação breve; quem investiga precisa do traceback original.

Diagrama mostrando uma exceção inesperada chegando à fronteira de uma CLI e se dividindo em uma mensagem breve para o usuário e um registro técnico com traceback, ambos enviados para stderr, com código de saída 1.

Para um defeito inesperado: stderr recebe a mensagem ao usuário e o diagnóstico identificado; o processo termina com código 1.

Capture, registre e retorne falha

Captura final na fronteira da CLI

Coloque este bloco depois dos tratamentos das falhas esperadas.

python
import logging
import sys


def main(argv: list[str] | None = None) -> int:
    try:
        configuracao = carregar_configuracao(argv)
        resultado = consultar_registro(configuracao)
    except ConfiguracaoInvalida as erro:
        print(f"Configuração inválida: {erro}. Revise a chave informada.", file=sys.stderr)
        return 3
    except RegistroNaoEncontrado as erro:
        print(f"Registro não encontrado: {erro}. Confira o identificador.", file=sys.stderr)
        return 3
    except Exception:
        logging.exception("Diagnóstico: defeito inesperado durante a consulta")
        print("Não foi possível concluir a operação. Tente novamente mais tarde.", file=sys.stderr)
        return 1
    else:
        print(resultado)
        return 0


if __name__ == "__main__":
    raise SystemExit(main())

Por que logging.exception?

Dentro de um bloco except, logging.exception(...) registra a mensagem e o traceback da exceção ativa. Assim, a evidência da origem do defeito não se perde.

A mensagem de print(..., file=sys.stderr) é breve e acionável. Nenhum resultado de sucesso vai para stdout nesse caminho.

Registre com prudência

Atenção

Diagnóstico não é despejo de dados

Não inclua senhas, tokens, conteúdo completo de arquivos de configuração ou dados pessoais no texto do log. Também não afirme que houve recuperação, nem culpe o usuário, sem evidência.

A captura é de Exception, não de BaseException: isso preserva sinais de encerramento como SystemExit.

Escolha o tratamento adequado

Após os tratamentos específicos de falhas previstas, qual bloco trata corretamente um defeito inesperado?

Passo 7 de 7

Aplique e confira o contrato completo

Execute uma CLI autocontida em seis cenários e compare canais, mensagens, diagnóstico e código de saída.

Uma CLI completa para experimentar

Copie e salve o script

Crie um arquivo chamado consulta.py em uma pasta vazia e cole o código abaixo. Ele contém dados, configuração simulada e um defeito controlado por --bug, para que você possa observar todo o contrato sem depender de um projeto anterior.

A fronteira da CLI está em main: ela imprime o resultado em stdout, traduz falhas previstas para stderr e retorna os códigos contratados. O bloco final é o único ponto que encerra o processo.

consulta.py

python
import argparse
import logging
import sys


class ConfiguracaoInvalida(Exception):
    pass


class RegistroNaoEncontrado(Exception):
    pass


REGISTROS = {
    "ana": {"nome": "Ana", "cidade": "Recife"},
    "bruno": {"nome": "Bruno", "cidade": "Curitiba"},
}


def carregar_configuracao(nome: str) -> None:
    if nome == "invalida":
        raise ConfiguracaoInvalida(
            "a configuração solicitada não passou na validação"
        )


def consultar_registro(identificador: str, provocar_bug: bool) -> dict[str, str]:
    if provocar_bug:
        raise RuntimeError("falha simulada no adaptador de dados")
    try:
        return REGISTROS[identificador]
    except KeyError as erro:
        raise RegistroNaoEncontrado(identificador) from erro


def construir_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="Consulta um registro local.")
    parser.add_argument("identificador", help="identificador do registro")
    parser.add_argument(
        "--config",
        choices=["padrao", "invalida"],
        default="padrao",
        help="configuração simulada",
    )
    parser.add_argument(
        "--bug",
        action="store_true",
        help="provoca um defeito inesperado para demonstração",
    )
    return parser


def main(argv: list[str] | None = None) -> int:
    args = construir_parser().parse_args(argv)

    try:
        carregar_configuracao(args.config)
        registro = consultar_registro(args.identificador, args.bug)
    except ConfiguracaoInvalida:
        print(
            "Erro de configuração: revise a configuração solicitada e tente novamente.",
            file=sys.stderr,
        )
        return 3
    except RegistroNaoEncontrado as erro:
        print(
            f"Registro '{erro}' não foi encontrado. Confira o identificador e tente novamente.",
            file=sys.stderr,
        )
        return 3
    except Exception:
        logging.exception("Diagnóstico técnico: defeito inesperado durante a consulta")
        print(
            "Ocorreu um erro inesperado. Tente novamente mais tarde.",
            file=sys.stderr,
        )
        return 1

    print(f"{registro['nome']} — {registro['cidade']}")
    return 0


if __name__ == "__main__":
    logging.basicConfig(level=logging.ERROR, format="%(levelname)s: %(message)s")
    raise SystemExit(main())

Três saídas, uma execução

Mesmo que stdout e stderr apareçam juntos no terminal, o redirecionamento abaixo torna a separação visível. O traceback do cenário inesperado é uma evidência técnica; ele não transforma a falha em sucesso.

Diagrama mostrando uma CLI recebendo argumentos e se dividindo em stdout para resultado, stderr para orientação e diagnóstico, e código de saída para o shell.

Resultado, mensagem e código são evidências diferentes do mesmo contrato.

Execute os seis cenários

Leia os arquivos gerados

No terminal, entre na pasta que contém consulta.py. Em cada comando, stdout.txt e stderr.txt são substituídos. Consulte o código logo após executar Python: outro comando pode alterar o valor que o shell guarda.

No caso de --help, o argparse encerra com 0 e escreve em stdout. Sem o argumento obrigatório, ele escreve uso e erro em stderr e encerra com 2.

Bash (macOS, Linux ou Git Bash)

Execute os blocos um de cada vez. Depois de cada execução, os dois cat mostram os canais separados.

bash
# 1. Sucesso: stdout tem o registro; stderr fica vazio; código 0
python consulta.py ana >stdout.txt 2>stderr.txt; codigo=$?
printf 'codigo=%s\n' "$codigo"; cat stdout.txt; cat stderr.txt

# 2. Ajuda: stdout tem a ajuda; stderr fica vazio; código 0
python consulta.py --help >stdout.txt 2>stderr.txt; codigo=$?
printf 'codigo=%s\n' "$codigo"; cat stdout.txt; cat stderr.txt

# 3. Argumento inválido: stderr tem uso e erro; código 2
python consulta.py >stdout.txt 2>stderr.txt; codigo=$?
printf 'codigo=%s\n' "$codigo"; cat stdout.txt; cat stderr.txt

# 4. Configuração inválida: stderr orienta a revisão; código 3
python consulta.py ana --config invalida >stdout.txt 2>stderr.txt; codigo=$?
printf 'codigo=%s\n' "$codigo"; cat stdout.txt; cat stderr.txt

# 5. Registro ausente: stderr orienta conferir o identificador; código 3
python consulta.py carla >stdout.txt 2>stderr.txt; codigo=$?
printf 'codigo=%s\n' "$codigo"; cat stdout.txt; cat stderr.txt

# 6. Defeito controlado: stderr tem diagnóstico e mensagem breve; código 1
python consulta.py ana --bug >stdout.txt 2>stderr.txt; codigo=$?
printf 'codigo=%s\n' "$codigo"; cat stdout.txt; cat stderr.txt

PowerShell (Windows)

Execute os blocos um de cada vez. $LASTEXITCODE é copiado imediatamente para $codigo.

powershell
# 1. Sucesso
python .\consulta.py ana 1> stdout.txt 2> stderr.txt; $codigo = $LASTEXITCODE
"codigo=$codigo"; Get-Content stdout.txt; Get-Content stderr.txt

# 2. Ajuda
python .\consulta.py --help 1> stdout.txt 2> stderr.txt; $codigo = $LASTEXITCODE
"codigo=$codigo"; Get-Content stdout.txt; Get-Content stderr.txt

# 3. Argumento inválido
python .\consulta.py 1> stdout.txt 2> stderr.txt; $codigo = $LASTEXITCODE
"codigo=$codigo"; Get-Content stdout.txt; Get-Content stderr.txt

# 4. Configuração inválida
python .\consulta.py ana --config invalida 1> stdout.txt 2> stderr.txt; $codigo = $LASTEXITCODE
"codigo=$codigo"; Get-Content stdout.txt; Get-Content stderr.txt

# 5. Registro ausente
python .\consulta.py carla 1> stdout.txt 2> stderr.txt; $codigo = $LASTEXITCODE
"codigo=$codigo"; Get-Content stdout.txt; Get-Content stderr.txt

# 6. Defeito controlado
python .\consulta.py ana --bug 1> stdout.txt 2> stderr.txt; $codigo = $LASTEXITCODE
"codigo=$codigo"; Get-Content stdout.txt; Get-Content stderr.txt

Compare com a matriz do contrato

Exemplo

Evidência esperada

| Cenário | stdout | stderr | Código |
|---|---|---|---|
| ana | Ana — Recife | vazio | 0 |
| --help | ajuda do parser | vazio | 0 |
| sem identificador | vazio | uso e erro do parser | 2 |
| ana --config invalida | vazio | orientação para revisar a configuração | 3 |
| carla | vazio | orientação para conferir o identificador | 3 |
| ana --bug | vazio | ERROR: Diagnóstico técnico..., traceback e mensagem breve | 1 |

A redação exata da ajuda e do erro do argparse pode variar entre versões do Python. O essencial é o canal e o código. No último caso, procure tanto a mensagem ao usuário quanto o traceback registrado.

Relate sua verificação

Após executar os seis cenários, relate os canais e códigos que você observou. Inclua especificamente: onde apareceu a ajuda, os códigos das três categorias de falha e o que apareceu em stderr com --bug.

Escreva pelo menos 180 caracteres (0/180).

Síntese e próximo passo

Resumo

Contrato aplicado

Você reuniu os comportamentos da CLI em evidências observáveis.

  • stdout transporta o resultado de uma operação bem-sucedida; stderr transporta erros, orientações e diagnósticos.
  • O contrato usado foi: 0 para sucesso ou ajuda, 2 para uso incorreto, 3 para falhas esperadas e 1 para defeitos inesperados.
  • main retorna o código; raise SystemExit(main()) o entrega ao processo.
  • Capturas específicas produzem orientações úteis. A captura final de Exception registra o traceback e ainda sinaliza falha.
  • Redirecionar stdout e stderr permite conferir que nenhuma falha foi apresentada como resultado bem-sucedido.

Contrato de falhas concluído

Parabéns! Você concluiu: Traduzir falhas em mensagens e códigos de saída

Concluído! Agora você consegue separar resultados, mensagens e diagnósticos, além de verificar o código de saída em cenários reais. No próximo tutorial, essa CLI poderá ser preparada para distribuição.

Baixe o Aplicativo agora para ter acesso a + de 5000 cursos gratuitos, exercícios, certificado e muito conteúdo sem pagar nada!

  • Cursos online 100% gratuitos do início ao fim

    Milhares de cursos online em vídeo, ebooks e áudiobooks.

  • Mais de 60 mil exercícios gratuitos

    Para testar seus conhecimentos no decorrer dos cursos online

  • Certificado Digital gratuito válido em todo o Brasil

    Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail

Aplicativo Cursa na tela de ebook, na tela de curso em vídeo e na tela de exercícios do curso, mais o certificado de conclusão de curso