DEV Community

Cover image for Qual ORM usar no seu próximo projeto Python?
Leandro César
Leandro César

Posted on • Updated on

Qual ORM usar no seu próximo projeto Python?

O que é?

ORM (Object-Relational Mappers) é uma ferramenta fundamental para qualquer desenvolvedor que trabalha com bancos de dados relacionais. Ele permite acessar os dados usando a sintaxe de objetos em vez de SQL, tornando o código mais limpo e fácil de dar manutenção.

Para que serve?

Ele separa a lógica de banco de dados da lógica de negócios. Além disso, ele permite que você trabalhe com dados em um formato nativo de objetos Python, o que é mais intuitivo e fácil de trabalhar.

Quais são?

Quando se trata de escolher um ORM, existem várias opções para Python. As mais populares são:

Como escolher?

Ao escolher um ORM, é importante considerar suas necessidades específicas e avaliar as características das opções disponíveis.

Aqui, vamos comparar brevemente os principais ORMs disponíveis para Python e discutir as características, vantagens e desvantagens, para ajudá-lo a escolher a melhor opção para seu projeto.


peewee

peewee logo

peewee é uma escolha popular para projetos de pequeno e médio porte, oferece uma abstração simples e intuitiva do banco de dados, e é fácil de usar e aprender. Ele é uma boa escolha para projetos menores e mais simples, e pode ser uma boa opção para desenvolvedores iniciantes que estão começando a trabalhar com ORMs.

$ pip install peewee
Enter fullscreen mode Exit fullscreen mode
from datetime import datetime

from peewee import *

# define a conexão com o banco de dados
db = SqliteDatabase(":memory:")

# define a classe do modelo
class User(Model):
    id = IntegerField(primary_key=True)
    name = TextField()
    created_on = DateTimeField(default=datetime.now)

    class Meta:
        database = db


# cria a tabela
db.create_tables([User])
# cria um novo usuário
user = User(name="John Doe")
user.save()
# busca um usuário pelo id
user = User.get(User.id == 1)
print(user.name)
# atualiza o nome do usuário
user.name = "Jane Doe"
user.save()
# deleta o usuário
user.delete_instance()
Enter fullscreen mode Exit fullscreen mode

Pony ORM

Pony ORM logo

Pony ORM é muito semelhante ao peewee, uma escolha para projetos menores e mais simples, e boa opção para desenvolvedores iniciantes.

$ pip install pony
Enter fullscreen mode Exit fullscreen mode
from datetime import datetime

from pony.orm import *

# define a conexão com o banco de dados
db = Database()
db.bind(provider="sqlite", filename=":memory:")

# define a classe do modelo
class User(db.Entity):
    id = PrimaryKey(int, auto=True)
    name = Required(str)
    created_on = Required(datetime, default=datetime.now)


# cria as tabelas no banco de dados
db.generate_mapping(create_tables=True)

with db_session:
    # cria um novo usuário
    user = User(name="John Doe")
    commit()
    # busca um usuário pelo id
    user = User[1]
    print(user.name)
    # atualiza o nome do usuário
    user.name = "Jane Doe"
    commit()
    # deleta o usuário
    user.delete()
    commit()
Enter fullscreen mode Exit fullscreen mode

SQLAlchemy

SQLAlchemy logo

SQLAlchemy é considerado um dos ORMs mais maduros e completos disponíveis, oferecendo uma grande variedade de recursos para lidar com bancos de dados. Ele é uma boa escolha para projetos de médio e grande escala.

$ pip install sqlalchemy
Enter fullscreen mode Exit fullscreen mode
from datetime import datetime

from sqlalchemy import Column, DateTime, Integer, Text, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# define a conexão com o banco de dados
engine = create_engine("sqlite:///:memory:")

# define a classe do modelo
Base = declarative_base()


class User(Base):
    __tablename__ = "user"
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    created_on = Column(DateTime, default=datetime.utcnow)


# cria as tabelas no banco de dados
Base.metadata.create_all(bind=engine)
# cria uma sessão com o banco de dados
Session = sessionmaker(bind=engine)

with Session as session:
    # cria um novo usuário
    user = User(name="John Doe")
    session.add(user)
    session.commit()
    # busca um usuário pelo id
    user = session.query(User).get(1)
    print(user.name)
    # atualiza o nome do usuário
    user.name = "Jane Doe"
    session.commit()
    # deleta o usuário
    session.delete(user)
Enter fullscreen mode Exit fullscreen mode

Tortoise-ORM

Tortoise-ORM logo

Tortoise-ORM é construído sobre o asyncio e é projetado para aplicações que precisam de alta performance e escalabilidade, especialmente quando se trata de operações assíncronas. É uma boa escolha para projetos que exigem requisitos de concorrência e escalabilidade. Ele é fácil de usar e aprender e oferece uma abstração simples e intuitiva do banco de dados.

$ pip install tortoise-orm
Enter fullscreen mode Exit fullscreen mode

O Tortoise-orm utiliza funções await para as operações no banco de dados. Logo, deve ser executado dentro de uma função async.

# __main__.py
from datetime import datetime

from tortoise import Tortoise, fields, run_async
from tortoise.models import Model


# define a classe do modelo
class User(Model):
    id = fields.IntField(pk=True)
    name = fields.TextField()
    created_on = fields.DatetimeField(default=datetime.now)


async def run():
    # define a conexão com o banco de dados
    await Tortoise.init(
        db_url="sqlite://:memory:",
        modules={"models": ["__main__"]},
    )
    # cria as tabelas no banco de dados
    await Tortoise.generate_schemas()
    # cria um novo usuário
    user = await User.create(name="John Doe")
    # busca um usuário pelo id
    user = await User.get(id=1)
    print(user.name)
    # atualiza o nome do usuário
    user.name = "Jane Doe"
    await user.save()
    # deleta o usuário
    await user.delete()


run_async(run())
Enter fullscreen mode Exit fullscreen mode

Comparativo: versões do Python

peewee Pony ORM SQLAlchemy Tortoise-ORM
Python version 2.7+ or 3.4+ 2.7 or 3 2.7 or 3.6+ 3.6+

Comparativo: bancos de dados

peewee Pony ORM SQLAlchemy Tortoise-ORM
SQLite ✔️ ✔️ ✔️ ✔️
MySQL/MariaDB ✔️ ✔️ ✔️ ✔️
PostgreSQL ✔️ ✔️ ✔️ ✔️
Oracle ✔️ ✔️
Microsoft SQL Server ✔️
CockroachDB ✔️ ✔️

Em geral, não é recomendado usar o Django ORM em uma aplicação que não usa o Django. Isso se deve ao fato de que o Django ORM foi projetado especificamente para trabalhar com o framework Django e suas estruturas de dados. Ele pode não funcionar corretamente ou ter limitações em um ambiente fora do Django. Se você estiver familiarizado com o Django ORM e desejar usá-lo em uma aplicação não-Django, é possível fazê-lo. Mas devido a isso, ele não foi incluido nas comparações.

Qual é o melhor ORM...

Todos os ORMs mencionados são bons e têm suas próprias vantagens e desvantagens. A escolha do melhor ORM para um determinado projeto dependerá das necessidades específicas do projeto e das preferências do desenvolvedor.

Assim, vamos analisar considerando alguns cenários mais específicos e concretos.

...para operações rápidas nos dados?

A performance na execução das operações do banco, que costuma ser um dos indicadores mais procurados na hora de escolher um ORM, depende de vários fatores, como: o banco de dados usado, a complexidade das consultas e o tamanho do conjunto de dados.

Portanto, é difícil comparar diretamente a performance de diferentes ORMs sem considerar esses fatores. Mas foi realizado, no início de 2022, um benchmark entre os ORMs considerados diferentes cenários. Uma visão geral do benchmark pode ser visto no gráfico abaixo.

Disclaimer: o benchmark foi realizado por contribuidores do projeto Tortoise-ORM

Python ORM benchmark

Fonte: https://github.com/tortoise/orm-benchmarks

...para consultas de alta complexidade?

Para um projeto com consultas SQL de alta complexidade, SQLAlchemy é uma das melhores opções de ORM para Python. Ele oferece uma grande flexibilidade no que diz respeito a consultas, tanto através do uso de sua API de consultas nativa quanto através do uso de SQL bruto. Além disso, ele permite a utilização de expressões avançadas, sub-consultas e junções complexas, o que é útil para projetos com consultas complexas.

...para relacionamentos complexos entre os dados?

Para um projeto com relacionamentos complexos entre as tabelas, SQLAlchemy também é uma das melhores opções de ORM para Python. Ele oferece suporte a mapeamento objeto-relacional avançado (ORM) e suporta vários tipos de relacionamentos, incluindo relacionamentos um-para-um, um-para-muitos e muitos-para-muitos. Ele também permite a criação de tabelas de junção e tabelas de associação, o que é útil para lidar com relacionamentos complexos.

Os outros ORMs (peewee, Pony ORM e Tortoise-ORM) também suportam relacionamentos um-para-um, um-para-muitos e muitos-para-muitos, mas a diferença é que o SQLAlchemy tem uma abstração mais flexível e completa para trabalhar com relacionamentos complexos. Ele oferece suporte a mapeamento objeto-relacional avançado e recursos avançados de carregamento de dados, como lazy loading e eager loading, que permitem carregar dados relacionados de forma eficiente.

...para alta escabilidade?

Para um projeto que exige escalabilidade, SQLAlchemy também é uma das melhores opções de ORM para Python. Ele é amplamente utilizado em projetos de produção de grande escala e é uma boa escolha para projetos complexos que possam exigir escalabilidade e performance. Ele tem suporte a vários tipos de engenharia de dados, incluindo recursos de replicação e escalabilidade.

...para projetos menores e mais simples

Para um projeto menor e mais simples, que não exige uma grande quantidade de recursos avançados, o Pony ORM ou peewee podem ser boas opções. Eles são fáceis de usar e aprender e oferecem uma abstração simples e intuitiva do banco de dados.

...com melhor curva de aprendizado

Se você estiver começando a trabalhar com ORMs e deseja algo mais fácil de usar e aprender, o Pony ORM ou peewee podem ser boas opções. Eles têm uma curva de aprendizado menor do que o SQLAlchemy.

...para requisitos mínimos de escalabilidade

Para um projeto com requisitos mínimos de escalabilidade, o Pony ORM ou peewee também são boas opções. Eles são leves e fáceis de usar e podem ser suficientes para lidar com o tráfego e o volume de dados do seu projeto.

...para requisitos específicos de concorrência

Para um projeto com requisitos específicos de concorrência, o Tortoise-ORM é uma boa opção pois ele é construído sobre o asyncio e suporta vários bancos de dados.

...para requisitos mínimos de segurança

Para um projeto com requisitos mínimos de segurança e não precisar de recursos avançados de segurança, como proteção contra SQL injection, o Pony ORM ou peewee podem ser boas opções.

...para uso de banco de dados assíncrono

O Tortoise-ORM é construído sobre o asyncio e é uma boa opção para projetos que precisam de alta performance e escalabilidade, especialmente quando se trata de operações assíncronas.


Quais as diferenças entre peewee e Pony ORM?

Pony ORM e peewee são muito semelhantes em características, mas existem diferenças:

  • peewee é considerado mais leve e minimalista, enquanto Pony ORM é mais completo e tem mais recursos.
  • peewee tem uma sintaxe de consulta mais simples e intuitiva, enquanto Pony ORM tem uma sintaxe mais avançada e poderosa.
  • peewee tem uma documentação mais completa e melhor organizada, enquanto Pony ORM tem uma documentação menos completa.
  • peewee é mais rápido e tem menos dependências do que Pony ORM.

Em resumo, peewee é uma boa escolha se você estiver procurando por uma biblioteca simples e fácil de usar, enquanto Pony ORM é uma boa escolha se você precisar de mais recursos e flexibilidade.

Por que um ORM assíncrono?

No caso do Tortoise-ORM (e agora também, ainda em versão beta, o asyncio-SQLAlchemy), é importante entender quando é necessário um ORM assíncrono.

Os bancos de dados atualmente são extremamente rápidos para operações simples, e por isso na maioria das vezes não se faz necessário um ORM assíncrono. O problema que o asyncio resolve é quando você precisa lidar com muitas tarefas simultâneas, onde algumas podem inclusive bloquear o I/O (input/output, ou escrita/leitura) por tempo arbitrário.

Por exemplo, uma aplicação de bate-papo que atende milhares de usuários simultaneamente. A última coisa que você deseja é ter milhares de threads esperando a resposta de cada um desses usuários, pois isso consumirá desproporcionalmente muitos recursos de hardware. Então, o asyncio pode lidar facilmente com essa simultaneidade com uma sobrecarga bem menor.

Outros ORMs

Vale a pena destacar e conferir outros ORMs, que não foram levados na comparação:

  • SQLObject: ORM para fornecer uma interface de objeto para seu banco de dados, com tabelas como classes, linhas como instâncias e colunas como atributos
  • Storm: ORM da Canonical
  • GINO: um atípico ORM assíncrono
  • Orator: ORM com uma implementação ActiveRecord simples, mas bonita
  • ormar: mini-ORM assíncrono
  • Prisma Client Python: ORM de próxima geração, construído sobre o Prisma
  • Piccolo: ORM e construtor de consultas assíncrono e moderno

Considerações finais

De forma geral, SQLAlchemy é o ORM mais maduro e completos para Python, e é amplamente utilizado em projetos de produção de grande escala, ele é flexível e oferece uma grande variedade de recursos. Ele é uma boa escolha para projetos complexos e que possa exigir escalabilidade.

Pony ORM e peewee são ORMs mais simples e fáceis de usar, eles são bons para projetos menores e mais simples, e são uma boa escolha para desenvolvedores iniciantes, pois oferecem uma abstração simples e intuitiva do banco de dados.

Tortoise-ORM é outro ORM popular para Python, ele é construído sobre o asyncio e suporta SQLite, MySQL e PostgreSQL. Ele é fácil de usar e aprender e é uma boa escolha para projetos com requisitos de concorrência e escalabilidade.

Em resumo, cada ORM tem suas próprias características e recursos únicos, e a escolha do melhor ORM para um projeto dependerá das necessidades específicas do projeto, como a escalabilidade, complexidade das consultas e necessidade de concorrência.

É recomendável experimentar cada uma dessas bibliotecas e comparar as funcionalidades e facilidade antes de tomar uma decisão.

Latest comments (2)

Collapse
 
gabrielsimas profile image
Gabriel Simas

Muito obrigado, amigo! Esse post é um Oásis. Estou me aventurando no Python depois de maia de 20 anos trabalhando com C++, Java e .net... decidi aprendee Python tb... e estava mesmo procurando ORMs parecidos com o Entity Framework, Hibernate e JPA

Collapse
 
wallacesilva09 profile image
Wallace Silva

Muito bom esse artigo, eu gostei muito. Vlw.