Evento e callback
Entender a ocorrência que chega ao programa e a função chamada para tratá-la.
Vamos entender como um programa percebe uma ação, chamada evento, e chama uma função de resposta, chamada callback. A demonstração usa um observador de eventos (listener) e os nomes on_press e on_release para distinguir pressionar de soltar uma tecla. Não é preciso conhecer Python de antemão: cada parte será explicada antes de ser usada. O código será construído em etapas executáveis, com um teste logo após cada alteração e um teste integrado no final.
log.txt nem envia dados. Para encerrar normalmente, pressione e solte ESC. Se o programa não responder ao ESC, pressione Ctrl+C no mesmo terminal. Se o prompt não voltar, encerre o terminal do processo pela interface do VS Code.Entender a ocorrência que chega ao programa e a função chamada para tratá-la.
Diferenciar os eventos associados a on_press e on_release.
Editar, executar e conferir o arquivo após cada etapa, sem acumular erros.
Verificar os dois callbacks e o encerramento controlado por ESC.
Na Aula 1, o laboratório foi preparado e validado. Nesta aula não vamos refazer essa configuração sem necessidade. Vamos confirmar a pasta de trabalho e, depois, verificar o ambiente Python antes de instalar ou usar uma dependência.
No terminal integrado do VS Code, execute o comando abaixo.
pwd
Resultado esperado: o caminho termina em Laboratorio-Keyloggers.
Resultado observado: registre o caminho que apareceu. Se estiver em outra pasta, abra a pasta correta no VS Code antes de continuar.
Status: ☐ aprovado ☐ reprovado ☐ não executado.
Abra um terminal novo e ative o ambiente virtual criado na Aula 1.
cd "$HOME/Laboratorio-Keyloggers" source .venv/bin/activate python --version python -c "import sys; print(sys.executable)" echo "$XDG_SESSION_TYPE" echo "$DISPLAY"
Confirme a versão registrada na Aula 1 e que o caminho do interpretador termina em .venv/bin/python. As últimas duas linhas mostram o tipo de sessão gráfica e o servidor de exibição. Registre as saídas; não avance se o ambiente virtual não estiver ativo. Se DISPLAY aparecer vazio, abra o VS Code pelo menu gráfico do Linux Mint e crie um terminal integrado novo: o listener precisa herdar a sessão gráfica da VM. Se continuar vazio, pare e peça ajuda ao responsável pelo laboratório.
Registro: anote a versão, o caminho e o status do teste.
pynput usa o servidor gráfico X ou a interface uinput, que permite ao Linux criar dispositivos de entrada virtuais. uinput exige privilégios de administrador; não o use nesta aula e nunca execute o listener com sudo. Wayland é um sistema gráfico; XWayland é uma camada de compatibilidade para aplicativos feitos para o servidor X e pode limitar os eventos que recebem. Confira sua sessão com echo "$XDG_SESSION_TYPE"; se aparecer wayland e o teste não funcionar como descrito, pare e peça ao responsável para configurar uma sessão compatível. Consulte as limitações de plataforma documentadas pelo pynput.Um evento é uma ocorrência que um programa pode reconhecer e tratar. No teclado, pressionar uma tecla e soltá-la são eventos distintos. Uma tecla especial, como ESC ou uma seta, também pode gerar eventos, mesmo que não corresponda a uma letra digitada.
Uma função agrupa instruções que podem ser executadas quando chamadas. Um parâmetro é o nome que aparece na definição para receber um valor. Um callback é uma função entregue a outro componente para que esse componente a chame quando ocorrer uma situação específica.
Por exemplo, ao configurar on_press=ao_pressionar, não estamos escrevendo ao_pressionar(). Estamos passando a própria função ao listener. O listener poderá chamá-la quando detectar um pressionamento.
| Termo | Significado nesta aula | Exemplo |
|---|---|---|
| Evento | Ocorrência a ser tratada. | Uma tecla foi pressionada. |
| Função | Bloco de instruções nomeado. | def ao_pressionar(tecla): |
| Parâmetro | Nome que recebe o valor fornecido à função. | tecla |
| Callback | Função chamada pelo componente que acompanha o evento. | ao_pressionar associada a on_press. |
| Listener | Componente que observa eventos enquanto está ativo. | keyboard.Listener(...) |
on_pressAssocia um callback ao momento em que a biblioteca informa que uma tecla foi pressionada.
on_releaseAssocia outro callback ao momento em que a biblioteca informa que a tecla foi solta.
Precisamos da biblioteca pynput porque a demonstração usa pynput.keyboard.Listener, um observador que recebe eventos de teclado enquanto está ativo na VM. Antes de instalar, confira se o pacote já está disponível no ambiente virtual ativo:
python -m pip show pynput
Esperado: se instalado, o comando mostra nome, versão e localização. Se não for encontrado, instale somente no ambiente virtual do laboratório:
python -m pip install pynput
Depois da instalação, execute novamente python -m pip show pynput. Não avance até confirmar que o pacote está instalado no ambiente virtual ativo. Nunca execute a instalação com sudo.
Resultado observado/status: registre o que apareceu; marque aprovado, reprovado ou não executado.
No VS Code, com .venv ainda ativo, crie um arquivo chamado eventos_teclado.py na pasta do laboratório. Salve o arquivo antes de cada teste. A cada etapa, substitua ou acrescente exatamente o trecho indicado para que o arquivo permaneça executável.
python eventos_teclado.py no terminal. Registre o resultado antes de alterar o código novamente.As etapas abaixo estão em ordem de dependência: primeiro verificamos que o arquivo pode importar a biblioteca; depois definimos cada callback; em seguida ligamos os callbacks ao listener; por último adicionamos o encerramento por ESC e as mensagens de orientação. O teste de cada etapa acontece antes da próxima mudança.
Arquivo: eventos_teclado.py
from pynput import keyboard
Explicação: from pynput import keyboard importa o módulo que contém a interface de teclado que usaremos. Ainda não há listener ativo nem eventos sendo observados.
python eventos_teclado.py
Esperado: o terminal volta ao prompt sem erro e sem imprimir mensagens. Esse resultado é normal porque só existe uma importação.
Observado/status: anote a saída real; aprovado somente se a execução terminar sem erro.
Acrescente a função abaixo depois da importação. Neste ponto, o arquivo completo fica assim:
from pynput import keyboard
def ao_pressionar(tecla):
# Exibe o valor recebido quando o callback for chamado.
print(f"Pressionada: {tecla}")Explicação: def define a função; tecla é o parâmetro; a linha indentada exibe o valor recebido. A função está apenas definida — ainda não foi conectada a um listener, então não será chamada por eventos reais.
python eventos_teclado.py
Esperado: o terminal retorna ao prompt sem saída. O teste verifica que a função pode ser definida sem erro; ainda não comprova o recebimento de eventos. O teste funcional será feito quando a função for conectada ao listener.
Observado/status: registre o resultado; aprovado se não houver erro de sintaxe ou importação.
Acrescente o bloco with ao final do arquivo. O conteúdo completo passa a ser:
from pynput import keyboard
def ao_pressionar(tecla):
# Exibe o valor recebido quando o callback for chamado.
print(f"Pressionada: {tecla}")
# ESC oferece uma saída segura desde o primeiro teste ativo.
if tecla == keyboard.Key.esc:
print("Encerrando a demonstração.")
return False
with keyboard.Listener(on_press=ao_pressionar) as listener:
print("Demonstração ativa. Use somente teclas de teste.")
print("Pressione ESC para encerrar.")
listener.join()Explicação: keyboard.Listener(...) cria o observador; on_press=ao_pressionar passa a função como callback; with gerencia o recurso; listener.join() mantém o programa aguardando enquanto o listener está ativo.
python eventos_teclado.py
Com o terminal visível, pressione e solte poucas teclas fictícias, sem conteúdo sensível. Nesta etapa, o callback trata os pressionamentos. Para encerrar, pressione ESC; a condição está no callback de pressão.
Esperado: cada tecla de teste produz uma linha que começa com Pressionada:. Ao pressionar ESC, aparece Encerrando a demonstração. e o processo volta ao prompt. Se ESC não funcionar, use Ctrl+C no mesmo terminal.
Observado/status: anote as mensagens e confirme que o prompt voltou. Não marque aprovado sem executar.
Agora substitua o conteúdo do arquivo pelo código abaixo, que associa um callback a cada tipo de evento:
from pynput import keyboard
def ao_pressionar(tecla):
# Exibe o valor recebido no evento de pressão.
print(f"Pressionada: {tecla}")
# Por enquanto, ESC encerra quando é pressionada.
if tecla == keyboard.Key.esc:
print("Encerrando a demonstração.")
return False
def ao_soltar(tecla):
# Exibe o valor recebido no evento de liberação.
print(f"Solta: {tecla}")
with keyboard.Listener(
on_press=ao_pressionar,
on_release=ao_soltar,
) as listener:
print("Demonstração ativa. Use somente teclas de teste.")
print("Pressione ESC para encerrar.")
listener.join()Explicação: ao_soltar é uma segunda função. O argumento on_release=ao_soltar informa ao listener qual callback chamar quando a tecla for solta. A vírgula separa os argumentos de Listener.
python eventos_teclado.py
Com o terminal visível, pressione e solte algumas teclas fictícias. O encerramento por ESC ainda acontece no evento de pressão: use ESC para parar e aguarde o prompt retornar.
Esperado: para as teclas comuns de teste, aparecem linhas Pressionada: e Solta:. Uma pressão seguida da liberação correspondente deve gerar os dois tipos de mensagem. ESC encerra ao ser pressionada.
Observado/status: registre a saída e marque aprovado, reprovado ou não executado.
Agora vamos fazer o encerramento acontecer quando ESC for solta. Remova de ao_pressionar a condição de parada adicionada no passo anterior e coloque a verificação dentro de ao_soltar, como mostrado abaixo. Assim, o teste também demonstra a diferença entre pressionar e soltar:
def ao_soltar(tecla):
# Exibe o valor recebido no evento de liberação.
print(f"Solta: {tecla}")
# Se ESC for solta, solicita ao listener que pare.
if tecla == keyboard.Key.esc:
print("Encerrando a demonstração.")
return FalseExplicação: a condição compara o evento recebido com keyboard.Key.esc. A mensagem torna o encerramento visível. Retornar False neste callback pede ao listener que pare de observar eventos. As três linhas finais precisam estar dentro da função; a condição e o retorno também precisam respeitar a indentação mostrada.
python eventos_teclado.py
Pressione e solte algumas teclas de teste e, por último, pressione e solte ESC.
Esperado: ao soltar ESC, aparece Encerrando a demonstração. e o programa volta ao prompt. Se isso não acontecer, tente Ctrl+C no mesmo terminal; se o prompt não voltar, encerre o terminal do processo. Corrija a condição ou a indentação antes de avançar.
Observado/status: registre o comportamento real.
Atualize o bloco final para informar ao usuário quando a demonstração está ativa e como encerrá-la. O arquivo completo fica assim:
from pynput import keyboard
def ao_pressionar(tecla):
# Exibe o valor recebido no evento de pressão.
print(f"Pressionada: {tecla}")
# Por enquanto, ESC encerra quando é pressionada.
if tecla == keyboard.Key.esc:
print("Encerrando a demonstração.")
return False
def ao_soltar(tecla):
# Exibe o valor recebido no evento de liberação.
print(f"Solta: {tecla}")
# Se ESC for solta, solicita ao listener que pare.
if tecla == keyboard.Key.esc:
print("Encerrando a demonstração.")
return False
with keyboard.Listener(
on_press=ao_pressionar,
on_release=ao_soltar,
) as listener:
print("Demonstração ativa. Use somente teclas de teste.")
print("Pressione e solte ESC para encerrar.")
listener.join()Explicação: as mensagens ficam dentro do bloco with, depois que o listener é configurado. O join() mantém o fluxo principal aguardando. Quando ESC é solta e o callback retorna False, o listener termina e a execução volta ao terminal.
python eventos_teclado.py
Esperado: as duas mensagens de orientação aparecem; os dois callbacks exibem os eventos; ao soltar ESC, a mensagem de encerramento aparece e o processo termina. Se ESC não encerrar, tente Ctrl+C no mesmo terminal. Se o prompt não voltar, encerre o terminal pela interface do VS Code e investigue antes de prosseguir.
Observado/status: registre a saída real e marque aprovado, reprovado ou não executado.
O listener chama os callbacks para os eventos que a biblioteca reporta durante a execução.
O terminal permanece visível e apresenta mensagens de orientação e de evento.
Este arquivo não cria nem modifica log.txt; registros serão assunto da Aula 4.
Não há comunicação de rede nem envio de eventos para outra pessoa ou serviço.
O ponto defensivo é perceber que callbacks podem receber valores que revelam atividade do usuário. O fato de um programa ser curto não elimina o risco de privacidade. Mantenha a demonstração dentro do escopo autorizado, não use credenciais nem conteúdo privado e encerre o processo assim que concluir o teste.
Ctrl+C no terminal em que a demonstração está ativa. Confirme que o processo terminou e que o prompt voltou; se não voltar, encerre o terminal pela interface do VS Code e abra um novo antes de continuar.Antes do teste final, confira se o arquivo foi salvo e se o conteúdo corresponde ao bloco abaixo. Esse bloco reúne somente os elementos trabalhados nesta aula; não inclui armazenamento nem transmissão.
from pynput import keyboard
def ao_pressionar(tecla):
# Exibe o valor recebido no evento de pressão.
print(f"Pressionada: {tecla}")
# Por enquanto, ESC encerra quando é pressionada.
if tecla == keyboard.Key.esc:
print("Encerrando a demonstração.")
return False
def ao_soltar(tecla):
# Exibe o valor recebido no evento de liberação.
print(f"Solta: {tecla}")
# Se ESC for solta, solicita ao listener que pare.
if tecla == keyboard.Key.esc:
print("Encerrando a demonstração.")
return False
with keyboard.Listener(
on_press=ao_pressionar,
on_release=ao_soltar,
) as listener:
print("Demonstração ativa. Use somente teclas de teste.")
print("Pressione e solte ESC para encerrar.")
listener.join()python eventos_teclado.py
Pré-condições: terminal visível, ambiente virtual correto, pynput instalado e arquivo salvo.
Procedimento: confirme as mensagens de orientação; pressione e solte uma tecla comum de teste e uma tecla especial não sensível; depois pressione e solte ESC.
Resultado esperado: mensagens de pressão e soltura aparecem; ESC produz a mensagem de encerramento; o processo termina e o prompt retorna.
Resultado observado: descreva a saída real do terminal. Não copie dados privados.
Critério de aprovação: todos os comportamentos esperados foram observados, o encerramento ocorreu e nenhum dado foi salvo ou transmitido.
Status: ☐ aprovado ☐ reprovado ☐ não executado.
Se falhar: registre o erro, feche o terminal do processo se necessário, corrija o problema e repita o teste completo. Não marque como aprovado com base apenas no resultado esperado.
Para cada passo de 1 a 6, registre:
python eventos_teclado.py.Antes de executar, escreva sua previsão. Depois rode o arquivo e compare sua previsão com o resultado observado. Use somente entradas de teste não sensíveis.
ao_pressionar() não faz a função executar imediatamente?tecla == keyboard.Key.esc verifica?return False no callback de soltura?Nesta aula, construímos uma demonstração transparente com pynput.keyboard.Listener, conectamos callbacks para pressão e liberação, e adicionamos um encerramento visível por ESC. Cada mudança deve ser testada imediatamente com python eventos_teclado.py, antes de seguir para a próxima.
Na próxima aula do cronograma, Aula 4 — Logs, Timestamps e Rastros, vamos estudar registros e timestamps usando dados de teste. Esta aula não grava as teclas em arquivo e não implementa transmissão de dados.