Módulos e a biblioteca padrão

O Python vem com uma enorme coleção de ferramentas prontas para usar: aleatoriedade, matemática, datas, caminhos de arquivo e muito mais. Essas ferramentas vivem em módulos, e você as traz para seu código com import. Você já usou import json no capítulo Arquivos e exceções. Este capítulo cobre imports completamente e introduz as partes mais úteis da biblioteca padrão.
Importando módulos
A importação mais simples traz um módulo inteiro e deixa você usar seu conteúdo com notação de ponto. Você também pode importar nomes específicos de um módulo para usá-los diretamente sem o prefixo. Aliases encurtam nomes longos.
import math
math.sqrt(16) # 4.0
math.pi # 3.141592653589793
math.floor(3.9) # 3
math.ceil(3.1) # 4Importe nomes específicos de um módulo para usá-los diretamente:
from math import sqrt, pi
sqrt(16) # 4.0 (sem o prefixo "math.")
pi # 3.141592653589793Dê a um módulo ou nome um alias para encurtá-lo:
import math as m
m.sqrt(16) # 4.0
from math import sqrt as square_root
square_root(25) # 5.0Aliases são comuns com bibliotecas de terceiros populares (import numpy as np, import pandas as pd). Para módulos da biblioteca padrão, prefira usar o nome completo; torna o código mais legível.
import math traz o módulo inteiro, depois você acessa com um ponto: math.sqrt(16). from math import sqrt pega um nome para que você possa dispensar o prefixo. A palavra-chave as renomeia um import longo, mas para coisas da biblioteca padrão o nome completo fica mais claro. random
O módulo random gera números aleatórios e faz escolhas aleatórias. Use para jogos, simulações, amostragem aleatória e qualquer outra coisa que precisa de imprevisibilidade. Definir uma seed torna os resultados reproduzíveis: a mesma seed produz a mesma sequência toda vez.
import random
random.random() # float entre 0 e 1 (exclusivo)
random.randint(1, 10) # inteiro de 1 a 10 (ambos inclusivos)
random.uniform(1.0, 10.0) # float entre 1.0 e 10.0
cores = ["vermelho", "verde", "azul"]
random.choice(cores) # escolhe um item
random.choices(cores, k=3) # escolhe k itens (com reposição)
random.sample(cores, k=2) # escolhe k itens (sem reposição)
numeros = [1, 2, 3, 4, 5]
random.shuffle(numeros) # embaralha no local, retorna NonePara resultados reproduzíveis (útil em testes e ciência de dados), defina uma seed antes de gerar:
random.seed(42)
random.randint(1, 100) # sempre o mesmo valor para seed 42A mesma seed produz a mesma sequência toda vez, em qualquer máquina.
random.choice() escolhe um item de uma lista, random.randint(1, 10) dá um número inteiro em um intervalo, fim incluído. Quer os mesmos resultados a cada execução, digamos para um teste? Chame random.seed() primeiro e a sequência fica travada. math
O módulo math adiciona operações matemáticas mais avançadas além dos operadores aritméticos básicos que você conheceu no capítulo Números. Raízes quadradas, potências, logaritmos, trigonometria e valores especiais como pi e infinito estão tudo aqui.
import math
math.sqrt(25) # 5.0
math.pow(2, 10) # 1024.0 (igual a 2 ** 10 mas sempre retorna float)
math.log(100, 10) # 2.0 (log base 10)
math.log(math.e) # 1.0 (log natural)
math.sin(math.pi / 2) # 1.0
math.cos(0) # 1.0
math.ceil(3.2) # 4
math.floor(3.9) # 3
math.trunc(3.9) # 3 (igual a int() para positivos)
math.inf # infinidade
math.isnan(float("nan")) # True
math.isinf(math.inf) # Truemath cobre tudo além de + - * /: raízes quadradas, potências, logs, trig, além de constantes como math.pi. Recorra a ela no momento em que um cálculo precisa de mais que os operadores básicos e você pula escrever a fórmula você mesmo. datetime
O módulo datetime lida com datas e horas. datetime.now() dá a você a data e hora atuais. strftime() formata como string. strptime() analisa uma string em um datetime. timedelta representa uma duração que você pode adicionar ou subtrair.
from datetime import datetime, date, timedelta
now = datetime.now() # data e hora atuais
today = date.today() # apenas data atual
print(now.year, now.month, now.day)
print(now.hour, now.minute, now.second)
# Formatação
print(now.strftime("%Y-%m-%d")) # "2024-01-15"
print(now.strftime("%d %B %Y, %H:%M")) # "15 de janeiro de 2024, 09:42"
# Análise
deadline = datetime.strptime("2024-12-31", "%Y-%m-%d")
# Aritmética
tomorrow = today + timedelta(days=1)
next_week = today + timedelta(weeks=1)
diff = deadline - now
print(f"{diff.days} dias até o prazo")Códigos comuns de strftime:
| Código | Significado | Exemplo |
|---|---|---|
%Y | Ano com 4 dígitos | 2024 |
%m | Mês (com zero) | 01 |
%d | Dia (com zero) | 15 |
%H | Hora (24h) | 09 |
%M | Minuto | 42 |
%B | Nome do mês completo | janeiro |
datetime.now() dá a você a data e hora atuais. strftime() a transforma em string com códigos como %Y-%m-%d, e strptime() vai de outro jeito, analisando uma string de volta. timedelta é uma duração que você pode adicionar ou subtrair, então today + timedelta(days=1) é amanhã. os e pathlib
pathlib é a forma moderna de trabalhar com caminhos de arquivo. Objetos Path deixam você construir, inspecionar e navegar caminhos usando o operador /. os dá acesso a variáveis de ambiente e operações de SO de nível inferior. Prefira pathlib para código novo.
from pathlib import Path
p = Path("data/reports")
p.exists() # True se o caminho existe
p.is_dir() # True se é um diretório
p.is_file() # True se é um arquivo
p.mkdir(parents=True, exist_ok=True) # criar diretórios
for f in p.glob("*.csv"): # todos os arquivos CSV no diretório
print(f.name) # o nome do arquivo
report = p / "report_jan.csv" # operador / une caminhos
report.stem # "report_jan" (nome sem extensão)
report.suffix # ".csv"
report.parent # Path("data/reports")
content = report.read_text() # ler conteúdo do arquivo diretamente
report.write_text("novo conteúdo\n") # escrever diretamentePara o módulo os:
import os
os.getcwd() # diretório de trabalho atual
os.listdir(".") # listar conteúdo do diretório
os.path.exists("data.txt") # True se caminho existe
os.path.join("data", "file.txt") # "data/file.txt" (multiplataforma)
os.environ.get("HOME") # ler uma variável de ambientePrefira pathlib para código novo. Use os quando precisar de variáveis de ambiente ou trabalhar com APIs antigas que esperam strings.
pathlib.Path trata um caminho de arquivo como um objeto que você pode investigar: .exists(), .read_text(), .write_text(), .glob(). O operador / une partes, então p / "report.csv" lê como um caminho real. Recorra a pathlib sobre o mais antigo os.path em código novo. timeit
timeit mede quanto tempo código leva para executar. É útil quando você quer comparar duas abordagens e escolher a mais rápida. Execute o código muitas vezes para obter uma medição estável.
import timeit
# Cronometrar uma declaração única
timeit.timeit("sum(range(1000))", number=10000)
# Cronometrar um bloco mais complexo
setup = "data = list(range(1000))"
code = "[x * 2 for x in data]"
time = timeit.timeit(code, setup=setup, number=10000)
print(f"{time:.4f} segundos para 10.000 execuções")number é quantas vezes repetir. Mais repetições dão uma medição mais estável.
timeit.timeit() cronometra um pedaço de código executando-o repetidamente, depois você divide pela contagem de execução para um número por chamada estável. É como você resolve "qual dessas duas é mais rápida" em vez de adivinhar. Uma execução é muito ruidosa para confiar, então deixe fazer loop. string
O módulo string fornece constantes de string pré-construídas para letras, dígitos e pontuação. Útil quando você precisa verificar caracteres ou gerar strings aleatórias de um alfabeto específico.
import string
string.ascii_lowercase # "abcdefghijklmnopqrstuvwxyz"
string.ascii_uppercase # "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
string.ascii_letters # ambos combinados
string.digits # "0123456789"
string.punctuation # todos os caracteres de pontuaçãoÚtil quando você precisa verificar caracteres ou gerar strings aleatórias:
import string, random
chars = string.ascii_letters + string.digits
password = "".join(random.choices(chars, k=12))string lhe dá conjuntos de caracteres prontos: string.ascii_letters, string.digits, string.punctuation. São strings simples, então você pode fazer loop sobre elas ou amostrar delas. Útil sempre que você precisa de um alfabeto conhecido para construir ou verificar contra. Criando seus próprios módulos
Qualquer arquivo Python é um módulo. Para usá-lo de outro arquivo, importe pelo nome do arquivo (sem .py). Você pode importar o módulo inteiro e usar seu conteúdo com notação de ponto, ou importar nomes específicos diretamente.
# utils.py
def clamp(value, lo, hi):
return max(lo, min(value, hi))
PI = 3.14159# main.py
import utils
utils.clamp(150, 0, 100) # 100
utils.PI # 3.14159
from utils import clamp
clamp(50, 0, 100) # 50Python encontra o módulo procurando no mesmo diretório que o arquivo que faz a importação (e alguns outros lugares). Para projetos maiores, módulos são organizados em pacotes: diretórios com um arquivo __init__.py.
.py é já um módulo: importe pelo nome do arquivo sem o .py, e suas funções e variáveis são suas para usar. import utils então utils.clamp(...), ou puxe um nome com from utils import clamp. É como você divide um programa crescente entre arquivos. __name__ == "__main__"
Quando Python executa um arquivo diretamente, __name__ é definido como "__main__". Quando o mesmo arquivo é importado como um módulo, __name__ é o nome do módulo. Este padrão deixa você escrever código que executa quando você executa o arquivo diretamente mas é ignorado quando o arquivo é importado por outro módulo.
# utils.py
def clamp(value, lo, hi):
return max(lo, min(value, hi))
if __name__ == "__main__":
# isto apenas executa quando você faz: python utils.py
# não quando você faz: import utils
print(clamp(150, 0, 100)) # 100Este é um padrão padrão para qualquer módulo que também é útil como um script autônomo.
if __name__ == "__main__": deixa um arquivo ser tanto um módulo importável quanto um script executável. Código sob a proteção executa quando você faz python utils.py, e é ignorado quando outro arquivo faz import utils. Útil para encolher uma demo rápida ou teste na parte inferior de um módulo. Destaques da biblioteca padrão
Alguns módulos a mais que valem a pena conhecer. Cada um resolve um problema comum que levaria trabalho significativo para implementar você mesmo.
collections: tipos de contêiner especializados:
from collections import Counter, defaultdict, deque
Counter(["a", "b", "a", "c", "a"]) # Counter({'a': 3, 'b': 1, 'c': 1})
defaultdict(list) # dict que cria automaticamente chaves faltantes
deque([1, 2, 3], maxlen=5) # append/pop rápido em ambas as extremidadesitertools: ferramentas para trabalhar com iteráveis:
import itertools
list(itertools.chain([1, 2], [3, 4])) # [1, 2, 3, 4]
list(itertools.islice(range(100), 5)) # [0, 1, 2, 3, 4]
list(itertools.combinations([1, 2, 3], 2)) # [(1, 2), (1, 3), (2, 3)]
list(itertools.product([0, 1], repeat=2)) # [(0,0), (0,1), (1,0), (1,1)]sys: acesso ao interpretador Python:
import sys
sys.argv # lista de argumentos de linha de comando
sys.exit(1) # sair com um código de status
sys.version # string de versão do PythonPacotes de terceiros: além da biblioteca padrão, pip instala pacotes da comunidade:
pip install requests # biblioteca HTTP
pip install pandas # manipulação de dados
pip install numpy # computação numéricaPacotes de terceiros estão fora do escopo deste guia, mas o padrão é sempre o mesmo: pip install, depois import.
Na prática
Combinando random, string e datetime para gerar IDs de jogo únicos com timestamps:
import random
import string
from datetime import datetime
def generate_game_id(length: int = 8) -> str:
chars = string.ascii_uppercase + string.digits
return "".join(random.choices(chars, k=length))
def timestamp() -> str:
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
game_id = generate_game_id()
print(f"[{timestamp()}] Iniciando jogo {game_id}")
scores = [random.randint(50, 100) for _ in range(5)]
print(f"Pontuações da rodada: {scores}")
print(f"Melhor: {max(scores)}")
