Noções Básicas de Scripting
10 exemplos para você começar com System Scripting - 7 básicos e 3 intermediários.
Pré-requisitos
uv venv && source .venv/bin/activate
# apenas stdlib para a maioria dos exemplos; typer opcional:
uv pip install "typer>=0.15"- Python 3.14.0 - os exemplos de scripting usam a biblioteca padrão primeiro.
Exemplos Básicos
1. Ponto de Entrada do Script
Proteja efeitos colaterais para que as importações permaneçam seguras.
def main() -> int:
print("executando")
return 0
if __name__ == "__main__":
raise SystemExit(main())main()retorna o código de saída inteiro para cron e CI.- Módulos importáveis não devem fazer chamadas de rede no momento da importação.
raise SystemExitevitasys.exitem código adjacente à biblioteca.
Relacionado: Scripts Robustos - códigos de saída e logging
2. CLI do argparse
Analise flags e argumentos posicionais sem dependências extras.
import argparse
def main() -> int:
parser = argparse.ArgumentParser(description="Arquivar logs")
parser.add_argument("--dry-run", action="store_true")
parser.add_argument("path")
args = parser.parse_args()
print(args.path, args.dry_run)
return 0
if __name__ == "__main__":
raise SystemExit(main())action="store_true"para flags booleanas.- O texto de ajuda é gerado automaticamente a partir de
ArgumentParser. - Valide caminhos após a análise, não dentro de
add_argumentpara regras complexas.
Relacionado: Automação de Arquivos e Diretórios - manipulação de caminhos
3. Caminhos pathlib
Caminhos orientados a objetos superam a concatenação de strings.
from pathlib import Path
root = Path("data")
for csv in root.glob("**/*.csv"):
print(csv.resolve())- O operador
/une segmentos de caminho de forma portátil. glob("**/*.csv")percorre recursivamente com**(siga links simbólicos com cuidado).- Use
.read_text(encoding="utf-8")em vez deopen()quando o arquivo inteiro couber na memória.
Relacionado: Automação de Arquivos e Diretórios - escritas seguras
4. Logging em vez de print
Logs estruturados sobrevivem a e-mails do cron e agregadores de logs.
import logging
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
log = logging.getLogger("backup")
def main() -> int:
log.info("iniciando backup")
return 0- Nível de log padrão INFO em scripts de produção; DEBUG via flag
--verbose. - Registre no stderr; mantenha o stdout limpo para consumidores de JSON/pipe.
- Inclua o contexto da operação nas mensagens de log, não grandes despejos de dados.
Relacionado: Scripts Robustos - logging operacional
5. Códigos de Saída Explícitos
Chamadores distinguem modos de falha por status de saída.
EXIT_OK = 0
EXIT_USAGE = 2
EXIT_FAIL = 1
def main() -> int:
return EXIT_OK- Documente os códigos em
--helpou README para operadores. 2comumente sinaliza erros de uso (argparse usa isso).- Nunca ignore exceções sem registrar e com saída não zero.
Relacionado: Scripts Robustos - tratamento de falhas
6. Variáveis de Ambiente
Leia a configuração do ambiente para scripts 12-factor.
import os
API_URL = os.environ.get("API_URL", "https://api.example.com")
TOKEN = os.environ["API_TOKEN"] # obrigatório - gera KeyError se ausente- Segredos obrigatórios: falhe rapidamente com uma mensagem clara se a variável de ambiente estiver ausente.
- Padrões apenas para conveniência de desenvolvimento não secreto.
- Nunca imprima variáveis de ambiente contendo tokens.
Relacionado: Trabalhando com APIs e Webhooks - chamadas autenticadas
7. Executando Subcomandos com Segurança
Delegue a ferramentas externas com listas de argumentos explícitas.
import subprocess
def run_git_status() -> int:
proc = subprocess.run(["git", "status", "--short"], check=False)
return proc.returncode- A forma de lista evita injeção de shell - sem
shell=Truea menos que seja inevitável. check=Falsepermite que você mapeie os códigos de retorno.- Capture a saída com
capture_output=Trueao analisar resultados.
Relacionado: subprocess e Interoperabilidade com Shell - captura e timeouts
Exemplos Intermediários
8. CLI Typer com Tipos
CLI tipada com menos boilerplate do que o argparse puro.
import typer
app = typer.Typer()
@app.command()
def greet(name: str, loud: bool = False) -> None:
msg = f"olá {name}"
typer.echo(msg.upper() if loud else msg)
if __name__ == "__main__":
app()- Typer é construído sobre Click - bom para ferramentas multi-comando.
- Dicas de tipo controlam a análise de opções e a validação.
- Emparelhe com
uv run script.pyna tabela de scripts dopyproject.toml.
Relacionado: Agendamento e Cron - CLIs typer agendadas
9. Arquivo de Configuração + Sobrescrita de CLI
Mescle padrões, configuração de arquivo e flags de CLI (o último vence).
from dataclasses import dataclass
@dataclass
class Config:
retries: int = 3
dry_run: bool = False
def resolve_config(cli_retries: int | None, base: Config) -> Config:
if cli_retries is not None:
return Config(retries=cli_retries, dry_run=base.dry_run)
return base- Precedência: padrões < arquivo de configuração < ambiente < CLI.
- Classes de dados
Configimutáveis simplificam os testes. - Valide a configuração mesclada antes de quaisquer efeitos colaterais.
Relacionado: Scripts Robustos - modo dry-run
10. Guardião Principal Idempotente
Pule o trabalho quando a saída já existir, a menos que --force.
from pathlib import Path
def build_report(out: Path, force: bool) -> int:
if out.exists() and not force:
print(f"pulando existente {out}")
return 0
out.write_text("dados do relatório\n", encoding="utf-8")
return 0- A idempotência torna os reexecuções do cron seguras.
--forcedocumenta a substituição intencional.- Escritas atômicas (arquivo temporário + renomear) evitam saídas parcialmente escritas - veja a página de automação de arquivos.
Relacionado: Automação de Arquivos e Diretórios - escritas atômicas
Versões da Stack: Esta página foi escrita para Python 3.14.0 (3.14 estável, 3.13 de manutenção), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+ e uv 0.6+.