【问题标题】:Multi - threading click macro / click recorder多线程点击宏/点击记录器
【发布时间】:2021-09-19 14:17:25
【问题描述】:

我正在编写一个脚本,它会在按下“q”按钮之前监听击键,然后它应该停止脚本并打印出每隔 2 秒保存的鼠标位置。我无法管理线程,我仍在学习这个主题。每次我运行代码时什么都没有发生,但进程正在运行:

from pynput.keyboard import Listener
import pyautogui
from multiprocessing import Process

import time

mouse_positions = []
def func1():
while True:
    time.sleep(2)
    mouse_positions.append(pyautogui.position())

cordinates = []
quit_status = False
keystrokes = []
    
def on_press(key):
    if "q" in str(key) :
        print('q was pressed!')
        exit("Stopped running")
        #qprint(key)
    keystrokes.append(key)
    print(keystrokes)
        #print(keystrokes)

if __name__ == '__main__':
    p1 = Process(target=func1)
    p1.start()
    p1.join()
    with Listener(on_press=on_press) as listener:  # Create an instance of Listener
        listener.join()  # Join the listener thread to the main thread to keep waiting for keys

编辑: 对于任何有兴趣的人,这是我构建的点击宏,我之前构建的脚本更像是鼠标捕获移动。下面的脚本将记录您的鼠标点击,然后重播它们。好多了。

from pynput.keyboard import Listener
import pyautogui
from pynput import mouse
import time

x_pos = []
y_pos = []
both_pos = []
pressed_key  = None

def on_click(x, y, button, pressed):
    if pressed:
        #print ("{0} {1}".format(x,y))
        print(pressed_key)
        if pressed_key == "1":
            both_pos.append("{0}".format(x,y))
            both_pos.append("{1}".format(x,y))
            #print("test" + x_pos + y_pos)
            print (x_pos + y_pos)
        else:
            pass
        if pressed_key == 'q':
            return False

def on_press(key):
    print("To replay press 'q' , to stop recording press '1' , to record again press '1' .")
    global pressed_key
    if 'Key.esc' in str(key):
        return False
    if '1' in str(key):
        pressed_key= None if pressed_key == '1' else '1'
    if 'q' in str(key):
        print("Replaying actions")
        print(str(len(both_pos)))
        for point in range(0,len(both_pos),2):
            time.sleep(3)
            print("clicking")
            pyautogui.click(x=int(both_pos[point]),y=int(both_pos[point+1]))
        print("done...")
        return False
        


mouse_listener = mouse.Listener(on_click=on_click)
mouse_listener.start()
with Listener(on_press=on_press) as listener:  # Create an instance of Listener
    listener.join()
    #print(mouse_listener.mouse_positions)

【问题讨论】:

    标签: python-3.x multithreading automation python-multiprocessing pyautogui


    【解决方案1】:

    您好,您可以使用threading 模块。 我创建了类MouseListener,它继承自threading.Thread 类。您想要运行的所有内容都放入 run 方法中。作为线程停止器,我使用了still_run 属性。 当您键入时,我传递给on_press 功能按键和mouse_listener。如果按下 q,我将 mouse_listener.still_run 设置为 False,这会导致鼠标监听器停止。

    mouse_positions 我从全局范围移动到MouseListener

    
    import threading
    
    from pynput.keyboard import Listener
    import pyautogui
    
    import time
    
    
    class MouseListener(threading.Thread):
        still_run = True
        mouse_positions = []
        def run(self):
            self.func()
    
        def func(self):
            while self.still_run:
                time.sleep(2)
                self.mouse_positions.append(pyautogui.position())
                print(self.mouse_positions)
    
    coordinates = []
    quit_status = False
    keystrokes = []
    
    
    def on_press(key, mouse_listener):
        print('kp')
        if "q" in str(key):
            print('q was pressed!')
            mouse_listener.still_run = False
            print(key)
            exit("Stopped running")
        keystrokes.append(key)
        print(keystrokes)
        print(keystrokes)
    
    
    if __name__ == '__main__':
        mouse_listener = MouseListener()
        mouse_listener.start()
        with Listener(on_press=lambda key: on_press(key, mouse_listener)) as listener:  # Create an instance of Listener
            listener.join()
        print(mouse_listener.mouse_positions)
    

    【讨论】:

    • 它正在工作!惊人的 !你介意解释一下我的代码有什么问题吗?
    • 如果我错了,请纠正我,on_press=lambda key: on_press(key, mouse_listener) 行 - 将这两个功能合二为一?您将“key”参数传递给 on_press 和 mouse_listener,然后从内部检查并将 status 更改为 false 以使其停止。但是执行 mouse_listener.start() 的那一刻会发生什么?线程的继承创建了一个只与 MouseListener 类相关的进程?启动后,您使用“listener.join()”将“listener”加入到使用 mouse_listener.start() 启动的进程中?
    • lambda 是匿名函数。默认情况下,Listener 期待可调用对象,并传递一个参数。所以lambda 充当on_press 函数的包装器。感谢lambda,我能够将另一个参数传递给on_press 函数。您已经定义了线程类,因此该类的每​​个实例都将作为独立线程运行。
    • 您的代码不工作的原因是p1.join()。根据定义: 其他线程可以调用一个线程的join()方法。这会阻塞调用线程,直到调用 join() 方法的线程终止。 因为您在p1 中有无限循环,所以您的程序永远不会到达with Listener ... 阶段,并且一直等到p1 是终止。这可以检查如果你把print('join complete')放在你的p1.join()命令之后,你会看到没有输出。
    • 非常感谢!你能推荐关于这个主题的udemy课程吗?仍然很难理解“with”是什么,它调用“Listener”函数并传递给“listener”对象,该对象又继承了“threading”类,这就是我们能够执行“listener.join()”的原因,完成后它会自行结束。
    猜你喜欢
    • 1970-01-01
    • 2023-02-14
    • 1970-01-01
    • 2013-03-20
    • 2020-07-15
    • 2020-03-06
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多