29. Interagindo com o Sistema Operacional: sys e os
Programas Python não existem isoladamente — eles rodam em um sistema operacional que gerencia arquivos, diretórios, configurações de ambiente e como programas iniciam e se comunicam. Os módulos sys e os fornecem ferramentas para interagir com esse ambiente, permitindo que seus programas aceitem argumentos de linha de comando, leiam variáveis de ambiente, naveguem pelo sistema de arquivos e criem ou removam diretórios.
Entender esses módulos transforma seus scripts Python de código isolado em programas que podem se integrar ao sistema mais amplo, responder à entrada do usuário na inicialização e gerenciar arquivos e pastas de forma programática.
29.1) Argumentos de Linha de Comando e Usando sys.argv
Quando você executa um script Python a partir do terminal ou prompt de comando, você pode passar informações adicionais para ele — isso são os argumentos de linha de comando (command-line arguments). Por exemplo:
python greet.py Alice 25Aqui, greet.py é o nome do script, e Alice e 25 são argumentos passados para o programa. O módulo sys fornece acesso a esses argumentos por meio de sys.argv, uma lista contendo o nome do script e todos os argumentos como strings.
29.1.1) O que é sys.argv?
sys.argv é uma lista em que:
sys.argv[0]é sempre o nome do script que está sendo executadosys.argv[1],sys.argv[2], etc., são os argumentos passados após o nome do script- Todos os elementos são strings, mesmo que pareçam números
Vamos criar um script simples para ver como isso funciona:
# show_args.py
import sys
print("Nome do script:", sys.argv[0])
print("Número de argumentos:", len(sys.argv))
print("Todos os argumentos:", sys.argv)Se você executar esse script com:
python show_args.py hello world 123Output:
Script name: show_args.py
Number of arguments: 4
All arguments: ['show_args.py', 'hello', 'world', '123']Repare que sys.argv contém 4 elementos: o nome do script mais três argumentos. O número 123 é armazenado como a string '123', não como um inteiro.
29.1.2) Usando Argumentos de Linha de Comando em Programas
Argumentos de linha de comando permitem que usuários personalizem o comportamento do programa sem modificar o código. Aqui está um programa de saudação que usa o primeiro argumento como nome:
# greet.py
import sys
if len(sys.argv) < 2:
print("Uso: python greet.py <name>")
sys.exit(1) # Sair com código de erro
name = sys.argv[1]
print(f"Hello, {name}!")Executando isso:
python greet.py AliceOutput:
Hello, Alice!Se você esquecer de fornecer um nome:
python greet.pyOutput:
Uso: python greet.py <name>O programa verifica se foram fornecidos argumentos suficientes. Se não, ele imprime uma mensagem de uso e sai com sys.exit(1). O número 1 é um código de saída (exit code) — por convenção, 0 significa sucesso e valores diferentes de zero indicam erros. Isso ajuda outros programas ou scripts a detectar se seu programa executou com sucesso.
29.1.3) Convertendo Argumentos para Outros Tipos
Como todos os argumentos chegam como strings, muitas vezes você precisa convertê-los. Aqui está um programa que calcula a área de um retângulo:
# area.py
import sys
if len(sys.argv) < 3:
print("Uso: python area.py <width> <height>")
sys.exit(1)
try:
width = float(sys.argv[1])
height = float(sys.argv[2])
except ValueError:
print("Error: Width and height must be numbers")
sys.exit(1)
area = width * height
print(f"Area: {area}")Executando isso:
python area.py 5.5 3.2Output:
Area: 17.6Se o usuário fornecer uma entrada inválida:
python area.py five threeOutput:
Error: Width and height must be numbersO bloco try-except (do Capítulo 25) lida com erros de conversão de forma elegante, fornecendo um feedback útil em vez de travar com um traceback.
29.2) Obtendo Informações do Interpretador e do Runtime com sys
O módulo sys fornece informações sobre o próprio interpretador Python e o ambiente de runtime. Isso é útil para debugging, logging, ou para escrever código que se adapta a diferentes versões do Python ou plataformas.
29.2.1) Informações de Versão do Python
sys.version e sys.version_info dizem qual versão do Python está executando seu código:
import sys
print("String da versão do Python:", sys.version)
print("Informações de versão:", sys.version_info)
print(f"Versão major: {sys.version_info.major}")
print(f"Versão minor: {sys.version_info.minor}")Output (example):
Python version string: 3.11.4 (main, Jul 5 2023, 13:45:01) [GCC 11.2.0]
Version info: sys.version_info(major=3, minor=11, micro=4, releaselevel='final', serial=0)
Major version: 3
Minor version: 11sys.version é uma string legível para humanos, enquanto sys.version_info é uma named tuple (tupla nomeada) que você pode comparar programaticamente:
import sys
if sys.version_info < (3, 8):
print("Este programa requer Python 3.8 ou superior")
sys.exit(1)
print("A versão do Python é compatível")Isso garante que seu programa só rode em versões do Python compatíveis.
29.2.2) Informações de Plataforma
sys.platform identifica o sistema operacional:
import sys
print("Plataforma:", sys.platform)
if sys.platform == "win32":
print("Executando no Windows")
elif sys.platform == "darwin":
print("Executando no macOS")
elif sys.platform.startswith("linux"):
print("Executando no Linux")
else:
print("Executando em outra plataforma")Output (on Linux):
Platform: linux
Running on LinuxIsso permite que você escreva código específico por plataforma quando necessário, como usar caminhos de arquivos ou comandos do sistema diferentes.
29.2.3) Caminho de Busca de Módulos
sys.path é uma lista de diretórios onde o Python procura quando você importa módulos:
import sys
print("Caminhos de busca de módulos:")
for path in sys.path:
print(f" {path}")Output (example):
Module search paths:
/home/user/projects
/usr/lib/python3.11
/usr/lib/python3.11/lib-dynload
/home/user/.local/lib/python3.11/site-packagesA primeira entrada geralmente é o diretório que contém seu script. O Python pesquisa esses caminhos em ordem quando você usa import. Entender sys.path ajuda a depurar erros de importação ou adicionar diretórios personalizados de módulos.
29.2.4) Encerrando Programas com Códigos de Saída
Já vimos sys.exit() sendo usado para parar programas. Você pode passar um código de saída para indicar sucesso ou falha:
import sys
def process_data(filename):
try:
with open(filename) as f:
data = f.read()
# Processar dados...
return True
except FileNotFoundError:
print(f"Error: File '{filename}' not found", file=sys.stderr)
return False
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python script.py <filename>", file=sys.stderr)
sys.exit(1)
success = process_data(sys.argv[1])
sys.exit(0 if success else 1)Códigos de saída seguem as convenções Unix:
0significa sucesso- Valores diferentes de zero indicam diferentes tipos de erro
- Outros programas podem checar esses códigos para determinar se seu programa teve sucesso
29.3) Acessando Variáveis de Ambiente com os
Variáveis de ambiente (environment variables) são pares chave-valor definidos pelo sistema operacional ou pelo usuário, que programas podem ler. Elas são usadas para configuração, para armazenar caminhos, chaves de API e outras configurações que não deveriam ser hardcoded.
29.3.1) Lendo Variáveis de Ambiente
O módulo os fornece os.environ, um objeto do tipo dicionário contendo todas as variáveis de ambiente:
import os
# Obter uma variável de ambiente específica
home = os.environ.get('HOME') # No Unix/Linux/macOS
print(f"Home directory: {home}")
# Retorna None se a variável não existir
api_key = os.environ.get('MY_API_KEY')
print(f"API key: {api_key}")Output (on Linux):
Home directory: /home/alice
API key: NoneVocê pode fornecer um valor padrão:
import os
# Obter variável de ambiente com valor padrão
log_level = os.environ.get('LOG_LEVEL', 'INFO')
print(f"Log level: {log_level}")Output (if LOG_LEVEL not set):
Log level: INFO29.3.2) Variáveis de Ambiente Comuns
Sistemas operacionais diferentes fornecem variáveis de ambiente padrão:
import os
# Variáveis multiplataforma
print("Path:", os.environ.get('PATH'))
# Unix/Linux/macOS
print("User:", os.environ.get('USER'))
print("Home:", os.environ.get('HOME'))
print("Shell:", os.environ.get('SHELL'))
# Windows
print("User", os.environ.get('USERNAME'))
print("User Profile:", os.environ.get('USERPROFILE'))
print("Temp:", os.environ.get('TEMP'))PATH é particularmente importante — ele lista diretórios onde o sistema procura programas executáveis. Quando você digita um comando como python, o sistema procura nesses diretórios.
29.3.3) Definindo Variáveis de Ambiente
Você pode modificar variáveis de ambiente para o seu programa e quaisquer subprocessos que ele criar:
import os
# Definir uma variável de ambiente
os.environ['MY_CONFIG'] = 'production'
# Ler de volta
print(os.environ.get('MY_CONFIG')) # Output: production
# Excluir uma variável de ambiente
del os.environ['MY_CONFIG']Importante: Alterações em os.environ afetam apenas o processo Python atual e quaisquer programas que ele iniciar. Elas não persistem depois que seu programa termina nem afetam outros programas.
29.4) Trabalhando com Caminhos de Arquivo e Diretórios (os.path, os.getcwd)
Gerenciar caminhos de arquivo corretamente é crucial para programas que trabalham com arquivos. Os módulos os e os.path fornecem ferramentas para construir, manipular e consultar caminhos de forma independente de plataforma.
29.4.1) Obtendo o Diretório de Trabalho Atual
O diretório de trabalho atual (current working directory, CWD) é a pasta que seu programa considera como ponto de partida para caminhos relativos:
import os
cwd = os.getcwd()
print(f"Current working directory: {cwd}")Output (example):
Current working directory: /home/alice/projects/myappQuando você abre um arquivo com um caminho relativo como 'data.txt', o Python procura no diretório de trabalho atual. Entender o CWD ajuda a depurar erros de "arquivo não encontrado".
29.4.2) Alterando o Diretório Atual
Você pode alterar o diretório de trabalho com os.chdir():
import os
original = os.getcwd()
print("Original directory:", original)
# Mudar para um diretório diferente
os.chdir('/tmp')
print("New directory:", os.getcwd())
# Voltar
os.chdir(original)
print("Back to:", os.getcwd())Output:
Original directory: /home/alice/projects
New directory: /tmp
Back to: /home/alice/projectsNota: No Capítulo 28, você aprendeu sobre contextlib.chdir(), que restaura automaticamente o diretório original. Para mudanças simples de diretório, prefira usar o context manager:
from contextlib import chdir
with chdir('/tmp'):
print("Temporarily in:", os.getcwd())
# Restaurado automaticamenteIsso garante que o diretório sempre seja restaurado, mesmo se ocorrer um erro.
29.4.3) Construindo Caminhos com os.path.join()
Sistemas operacionais diferentes usam separadores de caminho diferentes:
- Unix/Linux/macOS:
/(barra) - Windows:
\(barra invertida)
os.path.join() constrói caminhos corretamente para a plataforma atual:
import os
# Construir um caminho para um arquivo em um subdiretório
data_dir = 'data'
filename = 'users.txt'
filepath = os.path.join(data_dir, filename)
print(f"File path: {filepath}")Output (on Unix/Linux/macOS):
File path: data/users.txtOutput (on Windows):
File path: data\users.txtVocê pode juntar múltiplos componentes:
import os
base = '/home/alice'
project = 'myapp'
subdir = 'data'
file = 'config.json'
full_path = os.path.join(base, project, subdir, file)
print(full_path) # Output: /home/alice/myapp/data/config.jsonUsar os.path.join() torna seu código portátil entre sistemas operacionais.
29.4.4) Verificando se Caminhos Existem
Antes de trabalhar com arquivos ou diretórios, verifique se eles existem:
import os
path = 'data.txt'
if os.path.exists(path):
print(f"'{path}' exists")
else:
print(f"'{path}' does not exist")Você também pode verificar especificamente se é arquivo ou diretório:
import os
path = 'mydir'
if os.path.isfile(path):
print(f"'{path}' is a file")
elif os.path.isdir(path):
print(f"'{path}' is a directory")
elif os.path.exists(path):
print(f"'{path}' exists but is neither a file nor directory")
else:
print(f"'{path}' does not exist")Essas verificações evitam erros ao tentar abrir arquivos inexistentes ou listar diretórios inexistentes.
29.4.5) Obtendo Caminhos Absolutos
os.path.abspath() converte caminhos relativos em caminhos absolutos:
import os
relative_path = 'data/users.txt'
absolute_path = os.path.abspath(relative_path)
print(f"Relative: {relative_path}")
print(f"Absolute: {absolute_path}")Output (example):
Relative: data/users.txt
Absolute: /home/alice/projects/myapp/data/users.txtIsso é útil para logs, mensagens de erro, ou quando você precisa saber o caminho exato de um arquivo.
29.4.6) Dividindo Caminhos em Componentes
os.path.split() separa um caminho em diretório e nome do arquivo:
import os
path = '/home/alice/projects/data.txt'
directory, filename = os.path.split(path)
print(f"Directory: {directory}")
print(f"Filename: {filename}")Output:
Directory: /home/alice/projects
Filename: data.txtos.path.basename() pega apenas o nome do arquivo, e os.path.dirname() pega apenas o diretório:
import os
path = '/home/alice/projects/data.txt'
print(f"Basename: {os.path.basename(path)}") # Output: data.txt
print(f"Dirname: {os.path.dirname(path)}") # Output: /home/alice/projects29.4.7) Separando Extensões de Arquivo
os.path.splitext() separa o nome do arquivo de sua extensão:
import os
filename = 'report.pdf'
name, extension = os.path.splitext(filename)
print(f"Name: {name}") # Output: report
print(f"Extension: {extension}") # Output: .pdfIsso é útil para processar arquivos com base no tipo:
import os
files = ['data.csv', 'image.png', 'document.txt', 'script.py']
for file in files:
name, ext = os.path.splitext(file)
if ext == '.csv':
print(f"Process CSV file: {file}")
elif ext == '.png':
print(f"Process image file: {file}")Output:
Process CSV file: data.csv
Process image file: image.png29.5) Listando, Criando e Removendo Arquivos e Diretórios
O módulo os fornece funções para manipular o sistema de arquivos: listar conteúdo de diretórios, criar novos diretórios e remover arquivos e pastas.
29.5.1) Listando o Conteúdo de um Diretório
os.listdir() retorna uma lista de todos os itens em um diretório:
import os
# Listar conteúdo do diretório atual
contents = os.listdir('.')
print("Current directory contents:")
for item in contents:
print(f" {item}")Output (example):
Current directory contents:
script.py
data.txt
mydir
README.mdA lista inclui tanto arquivos quanto diretórios. Para distinguir entre eles:
import os
contents = os.listdir('.')
print("Files:")
for item in contents:
if os.path.isfile(item):
print(f" {item}")
print("\nDirectories:")
for item in contents:
if os.path.isdir(item):
print(f" {item}")Output:
Files:
script.py
data.txt
README.md
Directories:
mydir29.5.2) Criando Diretórios
os.mkdir() cria um único diretório:
import os
new_dir = 'output'
if not os.path.exists(new_dir):
os.mkdir(new_dir)
print(f"Created directory: {new_dir}")
else:
print(f"Directory already exists: {new_dir}")Output:
Created directory: outputImportante: os.mkdir() falha se o diretório pai não existir. Por exemplo, tentar criar 'data/output' quando 'data' não existe vai gerar um erro.
os.makedirs() cria todos os diretórios pais necessários:
import os
nested_dir = 'data/processed/2024'
if not os.path.exists(nested_dir):
os.makedirs(nested_dir)
print(f"Created directory structure: {nested_dir}")Output:
Created directory structure: data/processed/2024Isso cria data, depois data/processed, depois data/processed/2024 se eles não existirem.
29.5.3) Removendo Arquivos
os.remove() exclui um arquivo:
import os
filename = 'temp.txt'
# Criar um arquivo temporário
with open(filename, 'w') as f:
f.write('Temporary data')
print(f"File exists: {os.path.exists(filename)}") # Output: True
# Remover o arquivo
os.remove(filename)
print(f"File exists: {os.path.exists(filename)}") # Output: FalseAviso: os.remove() exclui arquivos permanentemente — eles não vão para a lixeira.
29.5.4) Removendo Diretórios
os.rmdir() remove um diretório vazio:
import os
directory = 'empty_dir'
# Criar e depois remover um diretório vazio
os.mkdir(directory)
print(f"Created: {directory}")
os.rmdir(directory)
print(f"Removed: {directory}")os.rmdir() falha se o diretório contiver arquivos. Para remover um diretório e todo o seu conteúdo, você precisa excluir os arquivos primeiro:
import os
def remove_directory_contents(directory):
"""Remove todos os arquivos em um diretório e então remove o diretório.
Nota: Falha se o diretório contiver subdiretórios.
"""
if not os.path.exists(directory):
print(f"Directory does not exist: {directory}")
return
# Remover todos os arquivos no diretório
for item in os.listdir(directory):
item_path = os.path.join(directory, item)
if os.path.isfile(item_path):
os.remove(item_path)
print(f"Removed file: {item_path}")
# Remover o diretório agora vazio
os.rmdir(directory)
print(f"Removed directory: {directory}")
# Exemplo de uso
test_dir = 'test_data'
os.makedirs(test_dir, exist_ok=True)
# Criar alguns arquivos de teste
with open(os.path.join(test_dir, 'file1.txt'), 'w') as f:
f.write('test')
with open(os.path.join(test_dir, 'file2.txt'), 'w') as f:
f.write('test')
# Remover tudo
remove_directory_contents(test_dir)Output:
Removed file: test_data/file1.txt
Removed file: test_data/file2.txt
Removed directory: test_dataNota: Para remoção de diretórios mais complexa (incluindo subdiretórios), o módulo shutil do Python fornece shutil.rmtree(), mas isso está além do nosso escopo atual.
29.5.5) Renomeando Arquivos e Diretórios
os.rename() renomeia ou move arquivos e diretórios:
import os
# Renomear um arquivo
old_name = 'draft.txt'
new_name = 'final.txt'
# Criar arquivo de teste
with open(old_name, 'w') as f:
f.write('content')
os.rename(old_name, new_name)
print(f"Renamed '{old_name}' to '{new_name}'")Você também pode mover arquivos para diretórios diferentes:
import os
# Criar diretórios e arquivo
os.makedirs('source', exist_ok=True)
os.makedirs('destination', exist_ok=True)
with open('source/file.txt', 'w') as f:
f.write('content')
# Mover arquivo para um diretório diferente
os.rename('source/file.txt', 'destination/file.txt')
print("Moved file to destination directory")Os módulos sys e os dão aos seus programas Python a capacidade de interagir com o sistema operacional, aceitar entrada pela linha de comando, ler configuração e gerenciar arquivos e diretórios. Essas capacidades transformam scripts simples em ferramentas poderosas de linha de comando que se integram perfeitamente ao ambiente mais amplo do sistema.