RPA Quaestvm
Abstrações e implementações úteis para RPA
Funcionalidades
Classe Logger
Abstração do logging padrão do python. Cria uma única instância do logger para cada caminho de arquivo.
No construtor, deve-se passar o caminho do arquivo de logs criado, o nome do logger (opcional) e o nível de logs (opcional)
def __init__(self, logs_path: str, name: str = 'RPA_Logger', level: str = 'INFO')
O método get_logger retorna a instância do objeto de acordo com o valor de logs_path, ou cria uma nova.
classe Pyautoqstvm
Essa clase possui métodos úteis para navegação desktop usando pyautogui, listados abaixo.
No construtor, pode-se passar um objeto da classe rpa_quaestvm.Logger e o caminho padrão das imagens de mapemaento:
from rpa_quaestvm.logger import Logger
from rpa_quaestvm.pyautoqstvm import Pyautoqstvm
logger = Logger.get_main_script_logger()
pyautoqstvm = Pyautoqstvm(logger=logger, pasta_imagens="mapeamento")
pyautoqstvm.espera_imagem(...)
def espera_imagem(
self,
imagem: str | list[str],
timeout: int = 10,
confidence: float = 0.9,
raise_errors: bool = True,
region: tuple[int, int, int, int] = None,
verbose: bool = True,
pasta_imagens: str = None,
extensao_imagem: str = 'png'
):
"""Aguarda uma imagem surgir na tela e captura sua posição usando pyautogui
Args:
imagem (str): nome da imagem a buscar, sem extensão e pasta raiz. o caminho completo será a concatenação dos parâmetros pasta_imagens, imagem e extensao_imagem
timeout (int, optional): quantos segundos esperar pela imagem na tela. Defaults to 10.
confidence (float, optional): parâmetro de confiança passado para o pyautogui. interfere em quanto a imagem real precisa estar fiel à passada por parâmetro. Defaults to 0.9.
raise_errors (bool, optional): se True, lança erro quando não encontra a imagem, se não retorna um booleano. Defaults to True.
region (tuple[int, int, int, int], optional): região específica da tela na qual procurar a imagem. Defaults to None.
verbose (bool, optional): se deve ou não logar informações usando o logger da biblioteca. Defaults to True.
pasta_imagens (str, optional): pasta na qual as imagens de mapeamento são salvas, relativa à raiz. Sobrepõe o valor passado no construtor, se tiver passado. Defaults to "mapeamento".
extensao_imagem (str, optional): extensão da imagem, sem o ponto. Defaults to 'png'.
Returns:
bool: se raise_errors for False e não achar a imagem
Box: se encontrar a imagem, retorna o objeto Box do pyautogui
"""
def get_coordenadas_location(
self,
location: Box,
horizontal: Literal["esquerda", "direita", "centro"] = "centro",
vertical: Literal["cima", "baixo", "centro"] = "centro",
):
"""busca as coordenadas de uma região específica dentro de uma Box
A região pode ser uma combinação dos valores horizontal e vertical, sendo retornada a coordenada
x e y daquele ponto.
Args:
location (Box): objeto retornado pelo pyautogui.locateOnScreen ou pelo pyautoqstvm.espera_imagem
horizontal (Literal["esquerda", "direita", "centro"], optional): região horizontal. Defaults to "centro".
vertical (Literal["cima", "baixo", "centro"], optional): região vertical. Defaults to "centro".
Raises:
ValueError: se os parâmetros horizontal ou vertical não forem válidos
Returns:
tuple(int, int): coordenadas x e y do ponto escolhido
"""
def espera_imagem_e_clica(
self,
imagem: str | list[str],
click: Literal["simples", "duplo", "triplo", "nada", "direito", "rodinha"] = "simples",
horizontal: Literal["esquerda", "direita", "centro"] = "centro",
vertical: Literal["cima", "baixo", "centro"] = "centro",
timeout: int = 10,
confidence: float = 0.9,
raise_errors: bool = True,
region: tuple[int, int, int, int] = None,
verbose: bool = True,
pasta_imagens: str = None,
extensao_imagem: str = 'png'
) -> bool:
"""
Espera por uma imagem na tela e clica nela. Usa os métodos espera_imagem e get_coordenadas_location
Args:
imagem (str): O caminho para o arquivo da imagem (.png) a ser localizada.
click_type (str): Tipo de clique: "simples" para clique único, "duplo" para clique duplo. "nada" para não clicar.
(Padrão: "simples")
horizontal (str): Posição horizontal do clique dentro da imagem:
"esquerda", "direita" ou "centro". (Padrão: "centro")
vertical (str): Posição vertical do clique dentro da imagem:
"cima", "baixo" ou "centro". (Padrão: "centro")
timeout (int): Tempo máximo em segundos para esperar pela imagem. (Padrão: 10)
confidence (float): Nível de confiança para a detecção da imagem (0.0 a 1.0).
Valores mais altos são mais estritos. (Padrão: 0.9)
raise_errors (bool, optional): se True, lança erro quando não encontra a imagem, se não retorna um booleano. Defaults to True.
region (tuple[int, int, int, int], optional): região específica da tela na qual procurar a imagem. Defaults to None.
verbose (bool, optional): se deve ou não logar informações usando o logger da biblioteca. Defaults to True.
pasta_imagens (str, optional): pasta na qual as imagens de mapeamento são salvas, relativa à raiz. Sobrepõe o valor passado no construtor, se tiver passado. Defaults to "mapeamento".
extensao_imagem (str, optional): extensão da imagem, sem o ponto. Defaults to 'png'.
Returns:
bool: se raise_errors for False e não achar a imagem
Box: se encontrar a imagem, retorna o objeto Box do pyautogui
"""
def limpar_campo(
self,
campo: str | tuple[int, int],
horizontal: str = "direita",
vertical: str = "centro",
):
"""Limpa um campo de texto usando atalhos de teclado (ctrl+a -> delete)
Args:
campo (str | tuple[int, int]): imagem a clicar (usando espera_imagem_e_clica), ou coordenadas x e y para clicar usando pyautogui.click
horizontal (str, optional): região horizontal do clique, se passou uma imagem como campo. Defaults to "direita".
vertical (str, optional): região vertical do clique, se passou uma imagem como campo. Defaults to "centro".
"""
def validar_presenca_imagem(
self,
imagem: str,
clique: Literal[
"simples", "duplo", "triplo", "nada", "direito", "rodinha"
] = "nada",
horizontal: Literal["esquerda", "direita", "centro"] = "centro",
vertical: Literal["cima", "baixo", "centro"] = "centro",
msg_erro: str = "Erro de validação de imagem",
deve_existir: bool = True,
campo_a_limpar: str | tuple[int, int] = None,
timeout: int = 1,
on_error: Callable | None = None,
confidence: float = 0.9,
region: tuple[int, int, int, int] = None,
):
"""Espera por uma imagem aparecer na tela, podendo realizar callbacks caso a imagem exista ou não
Args:
imagem (str): nome da imagem a buscar, sem extensão e pasta raiz. o caminho completo será a concatenação dos parâmetros pasta_imagens, imagem e extensao_imagem
clique (str): Tipo de clique: "simples" para clique único, "duplo" para clique duplo. "nada" para não clicar.
(Padrão: "simples")
horizontal (str): Posição horizontal do clique dentro da imagem:
"esquerda", "direita" ou "centro". (Padrão: "centro")
vertical (str): Posição vertical do clique dentro da imagem:
"cima", "baixo" ou "centro". (Padrão: "centro")
timeout (int): Tempo máximo em segundos para esperar pela imagem. (Padrão: 10)
confidence (float): Nível de confiança para a detecção da imagem (0.0 a 1.0).
Valores mais altos são mais estritos. (Padrão: 0.9)
region (tuple[int, int, int, int], optional): região específica da tela na qual procurar a imagem. Defaults to None.
verbose (bool, optional): se deve ou não logar informações usando o logger da biblioteca. Defaults to True.
pasta_imagens (str, optional): pasta na qual as imagens de mapeamento são salvas, relativa à raiz. Defaults to "mapeamento".
extensao_imagem (str, optional): extensão da imagem, sem o ponto. Defaults to 'png'.
msg_erro (str, optional): mensagem de erro lançada caso a validação falhe. Defaults to "Erro de validação de imagem".
deve_existir (bool, optional): se a imagem deve ser encontrada ou não. Se for False, a existência da imagem se torna um erro. Defaults to True.
campo_a_limpar (str | tuple[int, int], optional): nome da imagem ou coordenadas x e y passadas para o método limpar_campo caso a validação falhe. Defaults to None.
on_error (Callable | None, optional): método chamado em caso de erro, sem parâmetros. Defaults to None.
Raises:
Exception: caso a validação falhe
"""
def encerrar_task(self, task: str):
"""Encerra uma task do sistema usando taskkill
Args:
task (str): nome da task usada no taskkill
"""
def abrir_e_focar_aplicacao(
self,
caminho_executavel: str = None,
titulo_janela_re: str = ".*",
tempo_limite: int = 30,
):
"""
Inicia uma aplicação (se o caminho for fornecido) ou foca em uma já existente,
aguardando sua janela principal e dando foco a ela, utilizando apenas pyautogui.
Args:
caminho_executavel (str, opcional): O caminho completo para o executável da aplicação
(ex: "C:\\Windows\\notepad.exe").
Se não for fornecido, a função tentará focar em
uma janela existente com o título especificado.
titulo_janela_re (str): Uma expressão regular para o título da janela principal esperada.
Use ".*" para qualquer título (padrão).
tempo_limite (int): O tempo máximo em segundos para esperar a janela carregar.
Returns:
bool: True se a aplicação foi aberta/focada e a janela principal foi focada com sucesso,
False caso contrário.
"""
classe MiniConsole
Controla uma pequena janela sempre-visível (mini console) usada para acompanhar o progresso de um robô rodando sem interação, como numa VM. A janela roda em um subprocesso próprio (Tkinter) e recebe comandos via stdin, então não bloqueia a automação.
from rpa_quaestvm.miniconsole import MiniConsole
console = MiniConsole(logger=logger)
console.start()
console.log("Iniciando robô", line_number=1)
console.log("", line_number=2) # limpa uma linha
console.close()
log(text, line_number=None, log=True): escrevetextna linhaline_number(ou na próxima linha livre, empurrando as demais para cima, seline_numbernão for passado). Selog=True(padrão), também loga a mensagem pelo logger da instância.clear_line(line_number)/clear(): limpa uma linha específica ou a janela inteira.clear_and_write(text, log=True): limpa a janela e escrevetextna primeira linha.countdown(message, line_number, timeout): inicia uma contagem regressiva não bloqueante ("⏳ {message} ({segundos}s)") numa linha específica, em uma thread separada.
Cronômetro de progresso (ETA)
Para robôs que processam N itens em ciclos (ex: uma fatura por vez) e precisam estimar quanto tempo falta para terminar tudo:
console.start_progress(total=50, line_number=2, label="Tempo estimado")
for item in itens:
processar(item)
console.tick() # atualiza a linha 2 com o ETA e retorna o ETA em segundos
def start_progress(self, total: int, line_number: int, label: str = "Tempo estimado")
def tick(self, increment: int = 1) -> float | None
tick() calcula a média de tempo por ciclo já decorrido e projeta o tempo restante com base nos
ciclos que faltam, escrevendo algo como "Tempo estimado: 12m 30s restante (18/50)" na linha
configurada. Retorna o ETA em segundos (None se start_progress não foi chamado antes).
classe PauseController
Permite pausar/retomar ou interromper a automação em execução através de um atalho de teclado global (funciona mesmo com o foco em outra janela, já que o PyAutoGUI mantém o foco na aplicação sendo automatizada, não no script Python).
from rpa_quaestvm.pause_controller import PauseController
pause_controller = PauseController() # padrão: ctrl+alt+p pausa, ctrl+alt+q interrompe
console.log(pause_controller.dica_atalhos(), line_number=0)
while total > 0:
processar_proximo_item()
pause_controller.aguardar_se_pausado()
if pause_controller.deve_parar:
break
def __init__(
self,
pause_hotkey: str = "ctrl+alt+p",
stop_hotkey: str = "ctrl+alt+q",
logger: LoggerInstance | None = None,
)
def aguardar_se_pausado(self, poll_interval: float = 0.5)
def dica_atalhos(self) -> str
esta_pausado/deve_parar: properties booleanas com o estado atual.aguardar_se_pausado: bloqueia enquanto pausado; deve ser chamado nos pontos de checkpoint do loop principal (ex: entre um ciclo e outro).
classe StatusReporter
Reporta o progresso de uma automação (título da tarefa, ciclos concluídos/total, ETA) para uma API HTTP remota simples, útil para alimentar um painel de status externo quando o robô roda isolado numa VM. Nunca lança exceção — falhas de rede/API só geram um warning no log, sem derrubar a automação.
from rpa_quaestvm.status_reporter import StatusReporter
status_reporter = StatusReporter(
base_url="https://status.exemplo.com",
api_key="segredo",
robot_name="lancamento_de_faturas",
)
eta = console.tick()
status_reporter.enviar_status("Lançamento de Faturas no C5", done=18, total=50, eta_segundos=eta)
def __init__(
self,
base_url: str,
api_key: str,
robot_name: str,
logger: LoggerInstance | None = None,
timeout: float = 5,
intervalo_minimo: float = 5,
)
def enviar_status(
self,
task_title: str,
done: int,
total: int,
eta_segundos: float | None,
forcar: bool = False,
) -> bool
Por padrão, respeita um intervalo mínimo de 5s entre envios (intervalo_minimo) para não
disparar uma requisição HTTP por ciclo; use forcar=True para ignorar o intervalo (ex: no
primeiro ou último envio).
Metadata
Release files for rpa-quaestvm 1.11.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rpa_quaestvm-1.11.1.tar.gz | 43.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rpa_quaestvm-1.11.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 86.8 kB
Release files / rpa_quaestvm-1.11.1.tar.gz
| Download URL | rpa_quaestvm-1.11.1.tar.gz |
|---|---|
| Size | 43.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9bf6630ebe61dad82d69a9625a792d514fad1593bcf93747527147bfc960c9d9
|
|
BLAKE2b-256 checksum How to use checksums |
e01eae704cdb22e90dd29247281769d7092445ed430f22092cb2337761aabee2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / rpa_quaestvm-1.11.1-py3-none-any.whl
| Download URL | rpa_quaestvm-1.11.1-py3-none-any.whl |
|---|---|
| Size | 43.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a81880bb9fb51168af2eaafa801c0220362b57c13781e778d70900a19bc9b6cf
|
|
BLAKE2b-256 checksum How to use checksums |
e1c465bd08e7ba7b79b2a6a2e510be7475039b22dd4f7cb1aeb5742a3fb7a7e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|