Módulos os e sys do Python
Domine os módulos os e sys do Python: navegue no sistema de arquivos, gerencie variáveis de ambiente, inspecione o estado do interpretador e processe argumentos da linha de comando.
Os módulos os e sys são duas das ferramentas mais essenciais da biblioteca padrão do Python. O os conecta o Python ao sistema operacional subjacente — permitindo navegar por diretórios, inspecionar e definir variáveis de ambiente, e manipular arquivos e caminhos. O sys conecta o Python ao próprio interpretador — expondo a lista de argumentos, o caminho de busca de módulos e ganchos para controlar a saída do interpretador. Juntos, cobrem quase tudo o que um script precisa para interagir com o ambiente em que é executado.
O Módulo os
Importe os no topo do seu script:
import osNenhuma instalação é necessária; ele vem junto com toda distribuição Python.
Trabalhando com Diretórios
Obter e Alterar o Diretório de Trabalho Atual
os.getcwd() retorna o caminho absoluto do diretório onde seu script está sendo executado. os.chdir() o altera.
import os
# Print the current directory
print(os.getcwd())
# Example output: /Users/alice/projects
# Change to a different directory
os.chdir("/tmp")
print(os.getcwd())
# Output: /tmpListar o Conteúdo de um Diretório
os.listdir(path) retorna uma lista de todas as entradas (arquivos e subdiretórios) em path. Ele não percorre subdiretórios recursivamente.
import os
entries = os.listdir(".") # "." means current directory
for entry in sorted(entries):
print(entry)Para distinguir arquivos de diretórios, use os.path.isfile() e os.path.isdir():
import os
for entry in os.listdir("."):
if os.path.isdir(entry):
print(f"[DIR] {entry}")
else:
print(f"[FILE] {entry}")Criar e Remover Diretórios
import os
# Create a single directory
os.mkdir("reports")
# Create nested directories in one call
os.makedirs("data/2024/january", exist_ok=True)
# exist_ok=True prevents an error if the directory already exists
# Remove an empty directory
os.rmdir("reports")
# Remove a full directory tree
import shutil
shutil.rmtree("data")O parâmetro exist_ok=True em os.makedirs() é muito útil em scripts que podem ser executados mais de uma vez — sem ele, uma segunda execução levanta FileExistsError.
Percorrer uma Árvore de Diretórios
os.walk(top) gera uma tupla de três elementos (dirpath, dirnames, filenames) para cada diretório na árvore com raiz em top. É a forma padrão de percorrer recursivamente uma estrutura de pastas.
import os
for dirpath, dirnames, filenames in os.walk("project"):
level = dirpath.count(os.sep)
indent = " " * level
print(f"{indent}{os.path.basename(dirpath)}/")
for filename in filenames:
print(f"{indent} {filename}")Trabalhando com Caminhos de Arquivo
O submódulo os.path do Python contém utilitários portáteis de manipulação de caminhos que funcionam corretamente no Windows, macOS e Linux.
Unir Componentes de Caminho
os.path.join() combina partes de um caminho usando o separador correto para o sistema operacional atual.
import os
base = "/home/alice"
project = "myapp"
filename = "config.json"
full_path = os.path.join(base, project, filename)
print(full_path)
# Output: /home/alice/myapp/config.jsonNunca construa caminhos com concatenação de string como base + "/" + filename — isso quebra no Windows. Sempre use os.path.join().
Dividir um Caminho
import os
path = "/home/alice/myapp/config.json"
print(os.path.dirname(path)) # /home/alice/myapp
print(os.path.basename(path)) # config.json
print(os.path.split(path)) # ('/home/alice/myapp', 'config.json')
print(os.path.splitext(path)) # ('/home/alice/myapp/config', '.json')os.path.splitext() é conveniente quando você precisa remover ou alterar uma extensão de arquivo.
Verificar se um Caminho Existe
import os
print(os.path.exists("/tmp")) # True (usually)
print(os.path.isfile("/tmp")) # False — it is a directory
print(os.path.isdir("/tmp")) # True
print(os.path.isabs("/tmp")) # True — it is an absolute pathObter o Caminho Absoluto
os.path.abspath() resolve caminhos relativos em relação ao diretório de trabalho atual:
import os
print(os.path.abspath("config.json"))
# Example output: /home/alice/myapp/config.jsonIsso é útil quando você precisa armazenar ou registrar um caminho que deve permanecer válido mesmo que o diretório de trabalho mude posteriormente.
A Variável __file__ e Caminhos Relativos ao Script
Um problema comum: um script que abre "data.csv" funciona quando você o executa do seu próprio diretório, mas falha a partir de um diretório diferente. A solução é construir o caminho relativo ao próprio arquivo do script:
import os
# Directory that contains *this* script
HERE = os.path.dirname(os.path.abspath(__file__))
data_file = os.path.join(HERE, "data.csv")
with open(data_file, encoding="utf-8") as f:
content = f.read()Essa técnica torna os scripts portáteis independentemente de qual diretório você os inicia.
Variáveis de Ambiente
Variáveis de ambiente armazenam configurações que ficam fora do código-fonte — URLs de banco de dados, chaves de API, flags de funcionalidades, entre outros. O mapeamento os.environ oferece acesso de leitura e escrita ao ambiente do processo atual.
Ler uma Variável de Ambiente
import os
# Returns the value or None if not set
home = os.environ.get("HOME")
print(home)
# Example output: /home/alice
# Raise KeyError if not set (useful to fail fast on missing config)
path = os.environ["PATH"]Prefira os.environ.get(key) a os.environ[key] a menos que a variável seja estritamente necessária e o programa deva falhar sem ela.
Ler com um Valor Padrão
import os
debug = os.environ.get("DEBUG", "false")
port = int(os.environ.get("PORT", "8080"))
print(f"debug={debug}, port={port}")
# Output: debug=false, port=8080Definir e Excluir Variáveis de Ambiente
import os
# Set a variable — affects only the current process and its children
os.environ["MY_APP_ENV"] = "production"
# Remove a variable
os.environ.pop("MY_APP_ENV", None) # None prevents KeyError if not presentDefinir valores em os.environ não persiste após o término do processo. Para definir variáveis de ambiente permanentes, modifique seu perfil de shell (~/.bashrc, ~/.zshrc) ou use um arquivo .env carregado por uma biblioteca como python-dotenv.
Listar Todas as Variáveis de Ambiente
import os
for key, value in sorted(os.environ.items()):
print(f"{key}={value}")Executando Comandos do Shell com os.system() e subprocess
os.system(command) executa um comando do shell e retorna seu código de saída, mas não oferece forma de capturar sua saída. Para qualquer coisa além de uma chamada rápida sem necessidade de resposta, use o módulo subprocess em vez disso.
import os
import subprocess
# Quick way — exit code only
exit_code = os.system("echo hello")
print("exit code:", exit_code) # 0 means success
# Better way — capture output
result = subprocess.run(
["echo", "hello"],
capture_output=True,
text=True,
)
print(result.stdout.strip()) # hellosubprocess.run() é mais poderoso e seguro que os.system() porque evita o interpretador de shell e permite capturar stdout, stderr e o código de retorno como objetos Python.
Utilitários Úteis do os
| Função | O que faz |
|---|---|
os.getcwd() | Diretório de trabalho atual |
os.chdir(path) | Alterar o diretório de trabalho |
os.listdir(path) | Listar entradas do diretório |
os.mkdir(path) | Criar um diretório |
os.makedirs(path, exist_ok=True) | Criar diretórios aninhados |
os.rmdir(path) | Remover um diretório vazio |
os.remove(path) | Excluir um arquivo |
os.rename(src, dst) | Renomear / mover um arquivo |
os.walk(top) | Percorrer uma árvore de diretórios recursivamente |
os.environ | Mapeamento de variáveis de ambiente |
os.getpid() | ID do processo atual |
os.cpu_count() | Número de núcleos lógicos de CPU |
O Módulo sys
sys expõe informações sobre o interpretador Python e fornece ganchos para controlar seu comportamento.
import sysArgumentos da Linha de Comando com sys.argv
sys.argv é uma lista de strings. sys.argv[0] é o nome do script; os elementos subsequentes são os argumentos passados na linha de comando.
Suponha que você salve isso como greet.py e execute python greet.py Alice 42:
import sys
script_name = sys.argv[0] # 'greet.py'
name = sys.argv[1] # 'Alice'
age = sys.argv[2] # '42' — always a string
print(f"Hello, {name}! You are {age} years old.")
# Output: Hello, Alice! You are 42 years old.Sempre valide sys.argv antes de acessar índices — um IndexError vai travar o script se o usuário esquecer um argumento:
import sys
if len(sys.argv) != 3:
print(f"Usage: python {sys.argv[0]} <name> <age>")
sys.exit(1)
name = sys.argv[1]
age = sys.argv[2]
print(f"Hello, {name}! You are {age} years old.")Para análise complexa de argumentos, prefira o módulo argparse da biblioteca padrão — ele gera a saída de --help automaticamente.
Encerrar o Interpretador com sys.exit()
sys.exit(code) levanta SystemExit e encerra o interpretador. Por convenção, o código de saída 0 significa sucesso; qualquer valor diferente de zero sinaliza um erro.
import sys
answer = input("Continue? (y/n): ")
if answer.lower() != "y":
print("Goodbye!")
sys.exit(0)
print("Continuing...")Você pode capturar SystemExit em um bloco try/except se precisar executar limpeza antes do término do programa, mas geralmente a instrução with (para handles de arquivo, conexões de rede, etc.) lida com a limpeza automaticamente.
Informações sobre a Versão do Python
import sys
print(sys.version)
# Example: 3.10.15 (main, ...) [GCC 11.4.0]
print(sys.version_info)
# sys.version_info(major=3, minor=10, micro=15, ...)
# Guard against running on an unsupported Python version
if sys.version_info < (3, 8):
sys.exit("This script requires Python 3.8 or later.")sys.version_info é uma tupla nomeada, portanto você pode compará-la diretamente a uma tupla de inteiros.
O Caminho de Busca de Módulos (sys.path)
Quando você escreve import mymodule, o Python pesquisa cada diretório em sys.path em ordem até encontrar um arquivo correspondente. A lista começa com o diretório do script (ou uma string vazia para sessões interativas), seguido pelas entradas de PYTHONPATH, e depois a biblioteca padrão e os site-packages.
import sys
for p in sys.path:
print(p)Você pode acrescentar a sys.path em tempo de execução para importar módulos de locais não-padrão:
import sys
import os
# Add a sibling directory to the search path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "libs"))
import mymodule # now found in ./libs/mymodule.pyModificar sys.path é uma solução rápida para desenvolvimento local, mas para pacotes distribuíveis use pip e um pyproject.toml adequado.
Streams Padrão
sys.stdin, sys.stdout e sys.stderr são objetos semelhantes a arquivos conectados aos três streams padrão. Você pode redirecioná-los para capturar ou suprimir a saída.
import sys
# Write to stdout (same as print, but more explicit)
sys.stdout.write("Hello, stdout\n")
# Write to stderr (errors and diagnostics)
sys.stderr.write("Warning: something looks off\n")Um padrão comum em scripts é redirecionar sys.stdout para um arquivo a fim de capturar toda a saída de print():
import sys
with open("output.log", "w", encoding="utf-8") as log:
original_stdout = sys.stdout
sys.stdout = log
print("This goes to the log file.")
sys.stdout = original_stdout
print("This goes back to the terminal.")Atributos Úteis do sys
| Atributo / Função | O que retorna |
|---|---|
sys.argv | Lista de argumentos da linha de comando |
sys.version | string de versão do Python |
sys.version_info | Tupla nomeada de (major, minor, micro, ...) |
sys.platform | Identificador da plataforma ("linux", "darwin", "win32") |
sys.path | Caminho de busca de módulos (lista de strings) |
sys.modules | Dicionário de todos os módulos importados atualmente |
sys.stdin | Stream de entrada padrão |
sys.stdout | Stream de saída padrão |
sys.stderr | Stream de erro padrão |
sys.exit(code) | Encerrar o interpretador com o código de status fornecido |
sys.getrecursionlimit() | Profundidade máxima de recursão (padrão 1000) |
sys.maxsize | Valor máximo de um int nesta plataforma |
Combinando os e sys na Prática
Scripts reais frequentemente usam ambos os módulos juntos. Aqui está um exemplo pequeno, mas realista: um script que varre um diretório em busca de arquivos .log e exibe um resumo.
import os
import sys
def summarize_logs(directory):
if not os.path.isdir(directory):
sys.stderr.write(f"Error: '{directory}' is not a directory.\n")
sys.exit(1)
log_files = [
f for f in os.listdir(directory)
if f.endswith(".log") and os.path.isfile(os.path.join(directory, f))
]
if not log_files:
print("No .log files found.")
return
print(f"Found {len(log_files)} log file(s) in '{directory}':")
for name in sorted(log_files):
full_path = os.path.join(directory, name)
size = os.path.getsize(full_path)
print(f" {name} ({size} bytes)")
if len(sys.argv) != 2:
print(f"Usage: python {sys.argv[0]} <directory>")
sys.exit(1)
summarize_logs(sys.argv[1])Execute-o como python summarize.py /var/log e ele exibe o nome e o tamanho em bytes de cada arquivo .log naquele diretório.
os vs pathlib — Qual Usar?
O Python 3.4 introduziu pathlib.Path, uma alternativa orientada a objetos ao os.path. Ambas as abordagens são corretas; a escolha é principalmente uma preferência de estilo.
| Tarefa | Estilo os | Estilo pathlib |
|---|---|---|
| Unir caminhos | os.path.join(a, b) | Path(a) / b |
| Obter nome do arquivo | os.path.basename(p) | Path(p).name |
| Obter extensão | os.path.splitext(p)[1] | Path(p).suffix |
| Verificar se existe | os.path.exists(p) | Path(p).exists() |
| Ler arquivo de texto | open(p).read() | Path(p).read_text() |
| Listar diretório | os.listdir(p) | list(Path(p).iterdir()) |
pathlib tende a produzir código mais legível para scripts com muitas operações de caminho; os.path é familiar e suportado em qualquer lugar que o Python 3 seja executado. O módulo sys não tem equivalente em pathlib — é sempre import sys.
Prática
Capítulos Relacionados
- Módulos Python — criando e importando seus próprios módulos
- Manipulação de Arquivos em Python — lendo e gravando arquivos
- Python Try Except — tratando erros de operações de arquivo e de sistema operacional
- Variáveis Python — escopo e nomenclatura de variáveis
- Escopo Python — como o Python resolve nomes entre escopos