如何使用键盘和鼠标 Python 模块在文件中正确存储用户输入(键盘、鼠标)?
How to correctly store user input (keyboard,mouse) in file using keyboard & mouse Python modules?
我正在使用键盘和鼠标模块来记录用户与我们软件的交互,以便我们可以进行一些高级 GUI 测试。
目前我正在尝试将录制的事件存储在一个文本文件中,稍后再播放这段录音。
然而,当我从所述文件加载记录的事件时,我只看到播放的 mouse
事件和 没有 keyboard
事件。
此问题的一个原因可能是 KeyboardEvents 的实现。
KeyboardEvents 不包含 __repr__
的正确实现。这会阻止我们调用 print(keyboard_events, file=f)
并读取带有 eval(line)
的行。 (这适用于鼠标和 ButtonEvent 和 MoveEvent)
所以我们决定使用 KeyboardEvents 的 json 格式。基本上我们所做的是检索每个 KeyboardEvent 的 json 格式并将 json 写入文件。然后我们加载 json 文件并将 json 解析为 KeyboardEvents.
目前我们将鼠标和键盘输入存储在一个文件中。但是,由于 mouse
支持 __repr__
的正确实现,我们可以直接打印和鼠标事件并在其上使用 eval()
来检索存储的事件。
这是用于录音和播放的文件:
import threading
import mouse
import keyboard
from mouse import ButtonEvent
from mouse import MoveEvent
from mouse import WheelEvent
from keyboard import KeyboardEvent
import time
import json
import sys
def record(file='record.txt'):
f = open(file, 'w+')
mouse_events = []
keyboard_events = []
keyboard.start_recording()
starttime = time.time()
mouse.hook(mouse_events.append)
keyboard.wait('esc')
keyboard_events = keyboard.stop_recording()
mouse.unhook(mouse_events.append)
#first line = start of recording
#mouse events = second line
#keyboard events = every remaining line = 1 event
print(starttime, file=f)
print(mouse_events, file=f)
for kevent in range(0, len(keyboard_events)):
print(keyboard_events[kevent].to_json(), file = f)
f.close()
def play(file, speed = 0.5):
f = open(file, 'r')
#per definition the first line is mouse events and the rest is keyboard events
lines = f.readlines()
f.close()
mouse_events = eval(lines[1])
keyboard_events = []
for index in range(2,len(lines)):
keyboard_events.append(keyboard.KeyboardEvent(**json.loads(lines[index])))
starttime = float(lines[0])
keyboard_time_interval = keyboard_events[0].time - starttime
keyboard_time_interval /= speed
mouse_time_interval = mouse_events[0].time - starttime
mouse_time_interval /= speed
print(keyboard_time_interval)
print(mouse_time_interval)
#Keyboard threadings:
k_thread = threading.Thread(target = lambda : time.sleep(keyboard_time_interval) == keyboard.play(keyboard_events, speed_factor=speed) )
#Mouse threadings:
m_thread = threading.Thread(target = lambda : time.sleep(mouse_time_interval) == mouse.play(mouse_events, speed_factor=speed))
#start threads
m_thread.start()
k_thread.start()
#waiting for both threadings to be completed
k_thread.join()
m_thread.join()
if __name__ == '__main__':
if len(sys.argv) > 2 and sys.argv[1] == 'play':
play(sys.argv[2])
elif len(sys.argv) >= 2 and sys.argv[1] == 'record':
if(len(sys.argv)) == 3:
record(sys.argv[2])
else:
record()
else:
print("missing either 'play' or 'record' or filename")
我希望此代码的行为与在单个函数中 运行 相同(请参阅 中的编辑)。
含义:我希望同步线程中的播放并按下按键。我实际得到的是鼠标事件按需要播放但没有处理 KeyboardEvents。当我使用链接的 SO 中的函数时,它起作用了。
有人能给我指出正确的方向吗?
我忘了回答我自己的问题,但这里是:
感谢 blubberdiblub 的指导,我已经跟踪了跟踪的开始时间,然后可以在第一次输入发生时添加一个偏移量。这允许播放的时间稍微准确一些。
我正在使用键盘和鼠标模块来记录用户与我们软件的交互,以便我们可以进行一些高级 GUI 测试。 目前我正在尝试将录制的事件存储在一个文本文件中,稍后再播放这段录音。
然而,当我从所述文件加载记录的事件时,我只看到播放的 mouse
事件和 没有 keyboard
事件。
此问题的一个原因可能是 KeyboardEvents 的实现。
KeyboardEvents 不包含 __repr__
的正确实现。这会阻止我们调用 print(keyboard_events, file=f)
并读取带有 eval(line)
的行。 (这适用于鼠标和 ButtonEvent 和 MoveEvent)
所以我们决定使用 KeyboardEvents 的 json 格式。基本上我们所做的是检索每个 KeyboardEvent 的 json 格式并将 json 写入文件。然后我们加载 json 文件并将 json 解析为 KeyboardEvents.
目前我们将鼠标和键盘输入存储在一个文件中。但是,由于 mouse
支持 __repr__
的正确实现,我们可以直接打印和鼠标事件并在其上使用 eval()
来检索存储的事件。
这是用于录音和播放的文件:
import threading
import mouse
import keyboard
from mouse import ButtonEvent
from mouse import MoveEvent
from mouse import WheelEvent
from keyboard import KeyboardEvent
import time
import json
import sys
def record(file='record.txt'):
f = open(file, 'w+')
mouse_events = []
keyboard_events = []
keyboard.start_recording()
starttime = time.time()
mouse.hook(mouse_events.append)
keyboard.wait('esc')
keyboard_events = keyboard.stop_recording()
mouse.unhook(mouse_events.append)
#first line = start of recording
#mouse events = second line
#keyboard events = every remaining line = 1 event
print(starttime, file=f)
print(mouse_events, file=f)
for kevent in range(0, len(keyboard_events)):
print(keyboard_events[kevent].to_json(), file = f)
f.close()
def play(file, speed = 0.5):
f = open(file, 'r')
#per definition the first line is mouse events and the rest is keyboard events
lines = f.readlines()
f.close()
mouse_events = eval(lines[1])
keyboard_events = []
for index in range(2,len(lines)):
keyboard_events.append(keyboard.KeyboardEvent(**json.loads(lines[index])))
starttime = float(lines[0])
keyboard_time_interval = keyboard_events[0].time - starttime
keyboard_time_interval /= speed
mouse_time_interval = mouse_events[0].time - starttime
mouse_time_interval /= speed
print(keyboard_time_interval)
print(mouse_time_interval)
#Keyboard threadings:
k_thread = threading.Thread(target = lambda : time.sleep(keyboard_time_interval) == keyboard.play(keyboard_events, speed_factor=speed) )
#Mouse threadings:
m_thread = threading.Thread(target = lambda : time.sleep(mouse_time_interval) == mouse.play(mouse_events, speed_factor=speed))
#start threads
m_thread.start()
k_thread.start()
#waiting for both threadings to be completed
k_thread.join()
m_thread.join()
if __name__ == '__main__':
if len(sys.argv) > 2 and sys.argv[1] == 'play':
play(sys.argv[2])
elif len(sys.argv) >= 2 and sys.argv[1] == 'record':
if(len(sys.argv)) == 3:
record(sys.argv[2])
else:
record()
else:
print("missing either 'play' or 'record' or filename")
我希望此代码的行为与在单个函数中 运行 相同(请参阅
含义:我希望同步线程中的播放并按下按键。我实际得到的是鼠标事件按需要播放但没有处理 KeyboardEvents。当我使用链接的 SO 中的函数时,它起作用了。
有人能给我指出正确的方向吗?
我忘了回答我自己的问题,但这里是:
感谢 blubberdiblub 的指导,我已经跟踪了跟踪的开始时间,然后可以在第一次输入发生时添加一个偏移量。这允许播放的时间稍微准确一些。