Boas práticas no desenvolvimento de automações em Python
Agora que discutimos a legibilidade e manutenibilidade de código, o guia de estilo de código, o uso efetivo de comentários e documentação, a tipagem (typing), a validação de dados de entrada e a importância dos testes automatizados, podemos aplicar esses conceitos a um contexto prático muito comum com Python RPA que é a modularização e criação de pacotes escaláveis.
Por que criar pacotes Python para usar em automações escaláveis?
Ao desenvolver automações, frequentemente temos funções que se repetem entre diferentes robôs, como:
-
Ler arquivos CSV
-
Conectar em bancos de dados
-
Ler ou enviar e-mails
Empacotar essas funções em um pacote Python reutilizável permite:
-
Reusabilidade / Reuso: Módulos podem ser usados em diferentes processos, projetos ou robôs, sem necessidade de reescrever código.
-
Manutenibilidade / Manutenção: Alterações ou correções podem ser feitas em um único lugar, sem impactar outros módulos.
-
Escalabilidade: À medida que o número de processos aumenta, é fácil adicionar novos módulos e funcionalidades.
-
Facilidade de Testes: Testar módulos individualmente simplifica a identificação e resolução de problemas.
-
Padronização: Mantém consistência entre diferentes projetos e equipes.
-
Colaboração via PR: Permite revisar mudanças, manter a estabilidade da branch principal (main) e melhorar a qualidade do código.
Agora que entendemos a importância de criar pacotes reutilizáveis, podemos aplicar conceitos de legibilidade, manutenibilidade, tipagem e validação no contexto prático de modularização e criação de pacotes escaláveis para Python e automações inteligentes.
Modularização e Criação de Pacotes
A modularização é muito importante em projetos de automação, onde diversas ações, como interação com APIs, leitura de bancos de dados ou envio de e-mails, podem ser reutilizadas na mesma ou em diferentes automações.
Como Modularizar um projeto Python?
1 - Identificar Componentes Reutilizáveis
Primeiro, divida o fluxo do seu processo de automação em partes funcionais que podem ser modularizadas. Abaixo alguns exemplos comuns de componentes que podem ser modularizados:
- Conexões com sistemas: Como interação com bancos de dados, APIs e ERP.
- Ações repetitivas: Como logins, navegação em aplicativos e interações com interfaces de usuário.
- Processamento de dados: Leitura, transformação e armazenamento de dados.
- Geração de relatórios e notificações: Geração de logs, e-mails e alertas.
2 - Criar Módulos Reutilizáveis
Agora que você identificou os componentes reutilizáveis, crie módulos Python que encapsulam essas funcionalidades. Aqui estão alguns exemplos:
Módulo de Conexão com Banco de Dados:
# first_py/db_functions.py
import psycopg2
from typing import Optional
def conectar_db(host: str, usuario: str, senha: str, banco: str) -> Optional[psycopg2.extensions.connection]:
"""
Função para conectar a um banco de dados PostgreSQL.
Args:
host (str): Endereço do servidor do banco de dados.
usuario (str): Nome de usuário do banco de dados.
senha (str): Senha do banco de dados.
banco (str): Nome do banco de dados.
Returns:
Optional[psycopg2.extensions.connection]: Conexão com o banco de dados ou None em caso de erro.
"""
try:
conexao = psycopg2.connect(host=host, user=usuario, password=senha, database=banco)
return conexao
except Exception as e:
print(f"Erro ao conectar ao banco de dados: {e}")
return None
Módulo de leitura CSV:
# first_py/csv_functions.py
import csv
import os
def ler_csv(arquivo: str) -> list:
"""
Função para ler um arquivo CSV e retornar o conteúdo como uma lista de dicionários.
Args:
arquivo (str): Caminho do arquivo CSV.
Returns:
list: Lista de dicionários com o conteúdo do CSV.
"""
dados = []
if not os.path.exists(arquivo):
raise FileNotFoundError(f"O arquivo {arquivo} não foi encontrado.")
with open(arquivo, mode='r', newline='', encoding='utf-8') as file:
leitor = csv.DictReader(file)
for linha in leitor:
dados.append(linha)
return dados
Módulo que procura e lê e-mails:
# first_py/email_functions.py
from botcity.plugins.email import BotEmailPlugin
def ler_email(usuario: str, senha: str, assunto: str) -> list:
"""
Função para ler e-mails de uma conta do Gmail com base em um assunto.
Args:
usuario (str): Endereço de e-mail do usuário.
senha (str): Senha do e-mail do usuário.
assunto (str): Assunto a ser procurado.
Returns:
list: Lista de e-mails encontrados.
"""
email = BotEmailPlugin.config_email(MailServers.GMAIL, usuario, senha)
messages = email.search(f'SUBJECT "{assunto}"')
emails_info = []
for msg in messages:
email_data = {
"Date": msg.date_str,
"From": msg.from_,
"Message": msg.text
}
emails_info.append(email_data)
return emails_info
Importante
No exemplo estamos lidando com módulos de funções seguindo a programação funcional que foca em funções independentes que executam tarefas específicas. Mas, para projetos mais complexos a utilização de POO pode ser utilizada também, abaixo alguns motivos para seguir com a programação orientada a objetos:
-
Quando a automação envolve entidades complexas, como robôs, usuários, tarefas ou sistemas.
-
Quando a automação envolve interações complexas com múltiplas APIs, fluxos de trabalho e estados.
-
Quando você precisa de herança (por exemplo, diferentes tipos de robôs com comportamentos distintos, mas compartilhando algumas funcionalidades).
Veja a etapa de empacotamento detalhada no Lab seguinte.