Módulos e a biblioteca padrão
O Python vem com uma coleção enorme 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 o seu código com import. Você já usou import json no capítulo Arquivos e exceções. Este capítulo cobre imports em detalhes e apresenta as partes mais úteis da biblioteca padrão.
Importando módulos
O import mais simples traz um módulo inteiro e permite usar seu conteúdo com a 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 (não precisa do prefixo "math.")
pi # 3.141592653589793Dê um alias a um módulo ou nome 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 populares de terceiros (import numpy as np, import pandas as pd). Para módulos da biblioteca padrão, prefira usar o nome completo; isso torna o código mais legível.
import math traz o módulo inteiro, e então você acessa o conteúdo com um ponto: math.sqrt(16). from math import sqrt pega um único 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 se lê melhor. random
O módulo random gera números aleatórios e faz escolhas aleatórias. Use-o em jogos, simulações, amostragens aleatórias e qualquer outra coisa que precise de imprevisibilidade. Definir uma seed torna os resultados reproduzíveis: a mesma seed produz a mesma sequência sempre.
import random
random.random() # float entre 0 e 1 (exclusivo)
random.randint(1, 10) # inteiro de 1 a 10 (ambos inclusive)
random.uniform(1.0, 10.0) # float entre 1.0 e 10.0
colours = ["vermelho", "verde", "azul"]
random.choice(colours) # escolhe um item
random.choices(colours, k=3) # escolhe k itens (com reposição)
random.sample(colours, k=2) # escolhe k itens (sem reposição)
numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers) # 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 a seed 42A mesma seed produz a mesma sequência sempre, em qualquer máquina.
random.choice() escolhe um item de uma lista, random.randint(1, 10) dá um número inteiro dentro de um intervalo, incluindo o final. Quer os mesmos resultados a cada execução, digamos para um teste? Chame random.seed() antes e a sequência fica fixa. math
O módulo math adiciona operações matemáticas mais avançadas além dos operadores aritméticos básicos que você viu no capítulo Números. Raízes quadradas, potências, logaritmos, trigonometria e valores especiais como pi e infinito estão todos 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 na 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 # infinito
math.isnan(float("nan")) # True
math.isinf(math.inf) # Truemath cobre tudo além de + - * /: raízes quadradas, potências, logs, trigonometria, além de constantes como math.pi. Recorra a ele no momento em que um cálculo precisar de mais do que os operadores básicos, e você não terá que escrever a fórmula você mesmo. datetime
O módulo datetime lida com datas e horas. datetime.now() fornece a data e hora atuais. strftime() formata isso como uma string. strptime() converte uma string em um datetime. timedelta representa uma duração que você pode somar ou subtrair.
from datetime import datetime, date, timedelta
now = datetime.now() # data e hora atuais
today = date.today() # apenas a 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 January 2024, 09:42"
# Conversão de string
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} days until deadline")Códigos comuns de strftime:
| Código | Significado | Exemplo |
|---|---|---|
%Y | Ano com 4 dígitos | 2024 |
%m | Mês (com zero à esquerda) | 01 |
%d | Dia (com zero à esquerda) | 15 |
%H | Hora (24h) | 09 |
%M | Minuto | 42 |
%B | Nome completo do mês | January |
datetime.now() fornece a data e hora atuais. strftime() transforma isso em uma string com códigos como %Y-%m-%d, e strptime() faz o caminho contrário, convertendo uma string de volta. timedelta é uma duração que você pode somar ou subtrair, então today + timedelta(days=1) é amanhã. os e pathlib
pathlib é a forma moderna de trabalhar com caminhos de arquivo. Objetos Path permitem construir, inspecionar e navegar por caminhos usando o operador /. os dá acesso a variáveis de ambiente e operações de nível mais baixo do sistema operacional. Prefira pathlib para código novo.
from pathlib import Path
p = Path("data/reports")
p.exists() # True se o caminho existir
p.is_dir() # True se for um diretório
p.is_file() # True se for um arquivo
p.mkdir(parents=True, exist_ok=True) # cria os 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" # o operador / junta caminhos
report.stem # "report_jan" (nome sem a extensão)
report.suffix # ".csv"
report.parent # Path("data/reports")
content = report.read_text() # lê o conteúdo do arquivo diretamente
report.write_text("new content\n") # escreve diretamentePara o módulo os:
import os
os.getcwd() # diretório de trabalho atual
os.listdir(".") # lista o conteúdo do diretório
os.path.exists("data.txt") # True se o caminho existir
os.path.join("data", "file.txt") # "data/file.txt" (multiplataforma)
os.environ.get("HOME") # lê uma variável de ambientePrefira pathlib para código novo. Use os quando precisar de variáveis de ambiente ou trabalhar com APIs mais antigas que esperam strings.
pathlib.Path trata um caminho de arquivo como um objeto que você pode manipular: .exists(), .read_text(), .write_text(), .glob(). O operador / junta as partes, então p / "report.csv" se lê como um caminho de verdade. Prefira pathlib ao antigo os.path em código novo. timeit
timeit mede quanto tempo um 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
# Mede o tempo de uma única instrução
timeit.timeit("sum(range(1000))", number=10000)
# Mede o tempo de 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() mede o tempo de um trecho de código executando-o repetidamente, e então você divide pelo número de execuções para obter um valor estável por chamada. É assim que você resolve "qual dos dois é mais rápido" em vez de chutar. Uma única execução tem ruído demais para confiar, então deixe rodar em loop. string
O módulo string fornece constantes de string já prontas para letras, dígitos e pontuação. Útil quando você precisa verificar caracteres ou gerar strings aleatórias a partir 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 já prontos: string.ascii_letters, string.digits, string.punctuation. São strings comuns, então você pode percorrê-las ou amostrar delas. Útil sempre que você precisar de um alfabeto conhecido para construir ou verificar contra ele. Criando seus próprios módulos
Qualquer arquivo Python é um módulo. Para usá-lo em outro arquivo, importe-o pelo nome do arquivo (sem o .py). Você pode importar o módulo inteiro e usar seu conteúdo com a 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) # 50O Python encontra o módulo procurando no mesmo diretório do arquivo que está importando (e em mais alguns lugares). Para projetos maiores, os módulos são organizados em pacotes: diretórios com um arquivo __init__.py.
.py já é um módulo: importe-o pelo nome do arquivo sem o .py, e suas funções e variáveis ficam à sua disposição. import utils e depois utils.clamp(...), ou traga um único nome com from utils import clamp. É assim que você divide um programa em crescimento entre vários arquivos. __name__ == "__main__"
Quando o Python executa um arquivo diretamente, __name__ é definido como "__main__". Quando o mesmo arquivo é importado como um módulo, __name__ é o nome do módulo. Esse padrão permite escrever código que executa quando você roda 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__":
# isso só executa quando você faz: python utils.py
# não quando você faz: import utils
print(clamp(150, 0, 100)) # 100Este é um padrão comum para qualquer módulo que também é útil como script independente.
if __name__ == "__main__": permite que um arquivo seja tanto um módulo importável quanto um script executável. O código sob a guarda executa quando você faz python utils.py, e é ignorado quando outro arquivo faz import utils. Útil para encaixar uma demonstração ou teste rápido no final de um módulo. Destaques da biblioteca padrão
Mais alguns módulos que vale conhecer. Cada um resolve um problema comum que exigiria bastante trabalho para implementar por conta própria.
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 chaves ausentes automaticamente
deque([1, 2, 3], maxlen=5) # inserção/remoção rápida 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) # sai com um código de status
sys.version # string com a versão do PythonPacotes de terceiros: além da biblioteca padrão, 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 únicos de jogo 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()}] Starting game {game_id}")
scores = [random.randint(50, 100) for _ in range(5)]
print(f"Round scores: {scores}")
print(f"Best: {max(scores)}")
