StrEnum é uma classe da biblioteca padrão do Python criada para representar conjuntos fechados de valores textuais. Ela combina o comportamento de str com Enum, permitindo que cada membro funcione como uma string real sem abrir mão da organização, da legibilidade e da segurança proporcionadas por enumerações.
Esse recurso é especialmente útil em APIs, configurações, serialização JSON, comandos de terminal, validação de dados e integrações com bancos de dados. Em vez de espalhar strings mágicas pelo código, você centraliza valores válidos em uma única classe.
Por que usar StrEnum
Imagine uma aplicação que aceita os estados pending, running e done. Usar strings simples funciona no começo, mas qualquer erro de digitação pode passar despercebido. Com StrEnum, os valores válidos ficam explícitos e reutilizáveis.
from enum import StrEnum
class Status(StrEnum):
PENDING = "pending"
RUNNING = "running"
DONE = "done"
Agora Status.RUNNING é ao mesmo tempo um membro de enumeração e uma string compatível com muitas APIs existentes.
Diferença entre Enum e StrEnum
Com Enum tradicional, um membro não é automaticamente uma string. Já com StrEnum, comparações e operações comuns de texto se tornam mais naturais.
from enum import Enum, StrEnum
class CorEnum(Enum):
RED = "red"
class CorStr(StrEnum):
RED = "red"
print(CorStr.RED == "red") # True
print(CorEnum.RED == "red") # False
Essa diferença reduz conversões manuais com .value. Ainda assim, quando você precisa do valor bruto de forma explícita, membro.value continua disponível.
Valores automáticos com auto
StrEnum funciona com auto(). Por padrão, o nome do membro é convertido para letras minúsculas.
from enum import StrEnum, auto
class Ambiente(StrEnum):
DEVELOPMENT = auto()
STAGING = auto()
PRODUCTION = auto()
print(Ambiente.PRODUCTION.value) # production
Esse padrão é prático quando o valor textual deve seguir diretamente o nome do membro.
Uso em APIs
Em APIs REST, valores textuais aparecem em parâmetros, payloads e respostas. StrEnum ajuda a manter esses contratos consistentes.
class Formato(StrEnum):
JSON = "json"
CSV = "csv"
XML = "xml"
def exportar(formato: Formato):
if formato is Formato.JSON:
return {"resultado": []}
if formato is Formato.CSV:
return "resultado\n"
return " "
Para mais contexto sobre contratos HTTP, veja o guia de API REST com Python.
Conversão a partir de strings
Você pode construir um membro usando o valor textual.
entrada = "running"
status = Status(entrada)
print(status is Status.RUNNING)
Se o texto não existir, Python lança ValueError. Em entradas externas, trate esse caso para produzir mensagens claras.
def ler_status(texto: str) -> Status:
try:
return Status(texto)
except ValueError as erro:
validos = ", ".join(item.value for item in Status)
raise ValueError(f"status inválido; use: {validos}") from erro
Serialização JSON
Como os membros se comportam como strings, muitos serializadores JSON lidam com eles naturalmente.
import json
payload = {"status": Status.DONE}
print(json.dumps(payload))
Mesmo assim, teste o comportamento do framework usado no projeto. Algumas bibliotecas fazem verificações rígidas de tipo e podem exigir .value.
StrEnum em configurações
Valores de ambiente, níveis de log, estratégias de cache e modos de execução são bons candidatos.
class NivelLog(StrEnum):
DEBUG = "debug"
INFO = "info"
WARNING = "warning"
ERROR = "error"
Isso combina bem com variáveis de ambiente e arquivos de configuração. O artigo sobre variáveis de ambiente no Python mostra como organizar esse tipo de entrada.
Comparação e identidade
Comparar um membro com uma string pode ser conveniente, mas dentro da lógica de domínio prefira comparar membros da própria enumeração usando is ou igualdade entre membros. Isso deixa a intenção mais clara.
if status is Status.DONE:
print("processamento concluído")
Na fronteira da aplicação, como ao receber JSON, converta a string para o enum o mais cedo possível.
Iteração e listagem
Enumerar opções válidas é simples.
for status in Status:
print(status.name, status.value)
Esse recurso ajuda a gerar escolhas de CLI, documentação e mensagens de validação.
Uso com match
O pattern matching do Python torna o código legível.
def descrever(status: Status) -> str:
match status:
case Status.PENDING:
return "aguardando"
case Status.RUNNING:
return "em execução"
case Status.DONE:
return "concluído"
Veja também o tutorial sobre match case no Python.
Validação com type hints
Anotar parâmetros com StrEnum ajuda ferramentas estáticas e leitores do código.
def iniciar(ambiente: Ambiente) -> None:
print(f"iniciando em {ambiente}")
Para aprofundar esse tema, consulte type hints no Python.
Aliases e valores duplicados
Se dois nomes recebem o mesmo valor, o segundo normalmente vira um alias. Isso pode ser útil em migrações, mas também pode esconder duplicidades.
class Metodo(StrEnum):
GET = "get"
READ = "get"
Use aliases de forma deliberada e documentada. Em contratos externos, mudanças silenciosas podem confundir consumidores.
Customizando valores ausentes
É possível implementar _missing_ para aceitar variações controladas.
class Resposta(StrEnum):
YES = "yes"
NO = "no"
@classmethod
def _missing_(cls, value):
if isinstance(value, str):
value = value.strip().lower()
for item in cls:
if item.value == value:
return item
return None
Assim, entradas como " YES " podem ser normalizadas sem duplicar lógica fora da classe.
Cuidados com compatibilidade
StrEnum foi incorporado à biblioteca padrão em versões modernas do Python. Se o projeto suporta versões antigas, você pode usar uma combinação de str e Enum ou uma biblioteca de compatibilidade.
from enum import Enum
class StatusCompat(str, Enum):
PENDING = "pending"
RUNNING = "running"
O comportamento é semelhante, mas detalhes como representação textual podem variar. Teste integrações e serialização.
Boas práticas
Use StrEnum para conjuntos pequenos e fechados. Converta strings externas para membros na entrada da aplicação. Evite usar enumerações para valores que mudam frequentemente ou vêm de banco de dados. Prefira nomes claros, valores estáveis e documentação de qualquer alias.
Também vale escrever testes para conversão, serialização, valores inválidos e compatibilidade com frameworks. O conteúdo sobre pytest no Python pode ajudar.
Referências
Consulte a documentação oficial de StrEnum e a PEP 663 para entender decisões sobre representação e comportamento de enums baseados em strings.
Conclusão
StrEnum oferece uma forma moderna de modelar valores textuais controlados. Ele reduz strings mágicas, melhora validação, facilita serialização e torna contratos de domínio mais claros. Quando usado nas fronteiras certas, ajuda a manter aplicações Python previsíveis sem exigir conversões repetitivas ou estruturas complexas.







