---
title: "Python e PostgreSQL: Guia Completo"
url: "https://python.dev.br/blog/python-e-postgresql/"
markdown_url: "https://python.dev.br/blog/python-e-postgresql.MD"
description: "Conecte Python ao PostgreSQL usando psycopg2 e SQLAlchemy. Aprenda CRUD, queries avancadas, migrations e boas praticas de acesso a banco."
date: "2025-09-10"
author: "Equipe Python Brasil"
---

# Python e PostgreSQL: Guia Completo

Conecte Python ao PostgreSQL usando psycopg2 e SQLAlchemy. Aprenda CRUD, queries avancadas, migrations e boas praticas de acesso a banco.


PostgreSQL e um dos bancos de dados relacionais mais robustos e populares do mundo, e Python oferece ferramentas excelentes para trabalhar com ele. Neste guia, vamos desde a conexao basica com psycopg2 ate o uso avancado do SQLAlchemy como ORM completo.

## Configurando o Ambiente

Antes de comecar, instale as dependencias necessarias:

```bash
pip install psycopg2-binary sqlalchemy alembic
```

O pacote `psycopg2-binary` e a versao pre-compilada do driver PostgreSQL para Python. Para producao, recomenda-se usar `psycopg2` com as bibliotecas do sistema instaladas.

Certifique-se de ter um PostgreSQL rodando. Voce pode usar Docker para isso:

```bash
docker run --name pg-dev -e POSTGRES_PASSWORD=senha123 \
  -e POSTGRES_DB=meuprojeto -p 5432:5432 -d postgres:16
```

## Conexao Direta com Psycopg2

O psycopg2 e o driver mais utilizado para conectar Python ao PostgreSQL. Ele oferece controle total sobre as queries SQL:

```python
import psycopg2
from psycopg2.extras import RealDictCursor

def conectar():
    """Cria conexao com o PostgreSQL."""
    return psycopg2.connect(
        host="localhost",
        port=5432,
        database="meuprojeto",
        user="postgres",
        password="senha123",
    )

# Criando tabela
def criar_tabela():
    conn = conectar()
    cursor = conn.cursor()
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS produtos (
            id SERIAL PRIMARY KEY,
            nome VARCHAR(200) NOT NULL,
            preco NUMERIC(10, 2) NOT NULL,
            estoque INTEGER DEFAULT 0,
            criado_em TIMESTAMP DEFAULT NOW()
        )
    """)
    conn.commit()
    cursor.close()
    conn.close()

criar_tabela()
```

## Operacoes CRUD com Psycopg2

Vamos implementar as quatro operacoes basicas de forma segura, usando parametros para evitar SQL injection:

```python
def inserir_produto(nome: str, preco: float, estoque: int) -> int:
    """Insere um produto e retorna o ID gerado."""
    conn = conectar()
    cursor = conn.cursor()
    cursor.execute(
        "INSERT INTO produtos (nome, preco, estoque) VALUES (%s, %s, %s) RETURNING id",
        (nome, preco, estoque),
    )
    produto_id = cursor.fetchone()[0]
    conn.commit()
    cursor.close()
    conn.close()
    return produto_id

def listar_produtos() -> list[dict]:
    """Lista todos os produtos como dicionarios."""
    conn = conectar()
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    cursor.execute("SELECT * FROM produtos ORDER BY nome")
    produtos = cursor.fetchall()
    cursor.close()
    conn.close()
    return [dict(p) for p in produtos]

def atualizar_preco(produto_id: int, novo_preco: float) -> bool:
    """Atualiza o preco de um produto."""
    conn = conectar()
    cursor = conn.cursor()
    cursor.execute(
        "UPDATE produtos SET preco = %s WHERE id = %s",
        (novo_preco, produto_id),
    )
    atualizado = cursor.rowcount > 0
    conn.commit()
    cursor.close()
    conn.close()
    return atualizado

def deletar_produto(produto_id: int) -> bool:
    """Remove um produto pelo ID."""
    conn = conectar()
    cursor = conn.cursor()
    cursor.execute("DELETE FROM produtos WHERE id = %s", (produto_id,))
    deletado = cursor.rowcount > 0
    conn.commit()
    cursor.close()
    conn.close()
    return deletado

# Uso
novo_id = inserir_produto("Notebook Dell", 4599.90, 25)
print(f"Produto criado com ID: {novo_id}")

produtos = listar_produtos()
for p in produtos:
    print(f"  {p['nome']}: R$ {p['preco']}")
```

## Gerenciamento de Conexoes com Context Manager

Abrir e fechar conexoes manualmente e propenso a erros. Use context managers para garantir que os recursos sejam liberados:

```python
from contextlib import contextmanager

@contextmanager
def get_conexao():
    """Context manager para conexao com o banco."""
    conn = psycopg2.connect(
        host="localhost",
        database="meuprojeto",
        user="postgres",
        password="senha123",
    )
    try:
        yield conn
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()

@contextmanager
def get_cursor(conn):
    """Context manager para cursor."""
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    try:
        yield cursor
    finally:
        cursor.close()

# Uso limpo e seguro
with get_conexao() as conn:
    with get_cursor(conn) as cur:
        cur.execute("SELECT * FROM produtos WHERE preco > %s", (1000,))
        caros = cur.fetchall()
        for p in caros:
            print(f"{p['nome']}: R$ {p['preco']}")
```

## Usando SQLAlchemy como ORM

O SQLAlchemy e o ORM mais poderoso do ecossistema Python. Ele abstrai o SQL e permite trabalhar com objetos Python:

```python
from sqlalchemy import create_engine, Column, Integer, String, Numeric, DateTime
from sqlalchemy.orm import declarative_base, sessionmaker
from datetime import datetime

DATABASE_URL = "postgresql://postgres:senha123@localhost:5432/meuprojeto"

engine = create_engine(DATABASE_URL, echo=False)
Session = sessionmaker(bind=engine)
Base = declarative_base()

class Produto(Base):
    __tablename__ = "produtos_orm"

    id = Column(Integer, primary_key=True, autoincrement=True)
    nome = Column(String(200), nullable=False)
    preco = Column(Numeric(10, 2), nullable=False)
    estoque = Column(Integer, default=0)
    criado_em = Column(DateTime, default=datetime.utcnow)

    def __repr__(self):
        return f"<Produto(id={self.id}, nome='{self.nome}', preco={self.preco})>"

    def to_dict(self):
        return {
            "id": self.id,
            "nome": self.nome,
            "preco": float(self.preco),
            "estoque": self.estoque,
        }

# Criar tabela
Base.metadata.create_all(engine)
```

## CRUD com SQLAlchemy

As operacoes com o ORM sao mais intuitivas e seguras:

```python
def criar_produto_orm(nome: str, preco: float, estoque: int) -> Produto:
    session = Session()
    produto = Produto(nome=nome, preco=preco, estoque=estoque)
    session.add(produto)
    session.commit()
    session.refresh(produto)
    session.close()
    return produto

def buscar_produtos_por_faixa(preco_min: float, preco_max: float) -> list[dict]:
    session = Session()
    produtos = (
        session.query(Produto)
        .filter(Produto.preco.between(preco_min, preco_max))
        .order_by(Produto.preco)
        .all()
    )
    resultado = [p.to_dict() for p in produtos]
    session.close()
    return resultado

def atualizar_estoque(produto_id: int, quantidade: int) -> bool:
    session = Session()
    produto = session.query(Produto).filter_by(id=produto_id).first()
    if produto:
        produto.estoque += quantidade
        session.commit()
        session.close()
        return True
    session.close()
    return False

# Exemplo de uso
notebook = criar_produto_orm("Monitor LG 27'", 1899.90, 15)
print(f"Criado: {notebook}")

faixa = buscar_produtos_por_faixa(1000, 3000)
for p in faixa:
    print(f"  {p['nome']}: R$ {p['preco']:.2f}")
```

## Migrations com Alembic

Para gerenciar alteracoes no schema do banco, use o Alembic junto com o SQLAlchemy:

```bash
alembic init migrations
```

Configure o `alembic.ini` com a URL do banco e crie migracoes automaticamente:

```bash
alembic revision --autogenerate -m "criar tabela produtos"
alembic upgrade head
```

Isso permite versionar o schema do banco de dados junto com o codigo, facilitando deploys e trabalho em equipe.

## Boas Praticas

Ao trabalhar com Python e PostgreSQL, siga algumas praticas fundamentais. Sempre use queries parametrizadas para evitar SQL injection. Nunca concatene strings para montar SQL. Utilize connection pooling em aplicacoes web com `SQLAlchemy` ou `psycopg2.pool`. Mantenha as credenciais em variaveis de ambiente, nunca no codigo-fonte. Crie indices para colunas usadas em filtros e ordenacoes frequentes. E sempre feche conexoes e cursores apos o uso.

```python
import os

# Credenciais via variavel de ambiente
DATABASE_URL = os.environ.get(
    "DATABASE_URL",
    "postgresql://postgres:senha123@localhost:5432/meuprojeto"
)
```

## Conclusao

Python e PostgreSQL formam uma dupla extremamente produtiva. O psycopg2 oferece controle total sobre o SQL, enquanto o SQLAlchemy eleva a produtividade com um ORM completo. Combine ambos com Alembic para migrations e voce tera uma stack de dados robusta e profissional. Comece pelo psycopg2 para entender os fundamentos e migre para o SQLAlchemy conforme seu projeto crescer.

> **PostgreSQL em outras linguagens**: <a href="https://golang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">Go</a> com pgx oferece acesso de alta performance ao PostgreSQL com connection pooling nativo, ideal para microsservicos. <a href="https://kotlin.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'kotlin.dev.br' })">Kotlin</a> com Exposed traz um ORM type-safe que lembra o SQLAlchemy, mas com verificacao de tipos em tempo de compilacao.
