我如何创建一个定期输入键盘和鼠标输入的程序?

问题描述 投票:-1回答:1

我想要一个满足以下要求的程序:

  • 按键盘x终止程序
  • 按键盘y暂停或取消暂停程序
  • 虽然“暂停”该程序未输入键盘或鼠标数据
  • 虽然“不暂停”程序会定期触发程序生成的键盘和鼠标事件。

keyboard.add_hotkey('y',self.toggle)keyboard.add_hotkey('x',sys.exit)

本文最后是我到目前为止的代码。当前,

  • 程序始终处于“暂停”状态
  • 按键盘键'x'无法终止程序
  • 按键盘键'y'无法暂停或取消暂停程序

可以像这样安装第三方库keyboardmouse

[path to python]\Python38-32\python.exe -m pip install keyboard --user
[path to python]\Python38-32\python.exe -m pip install mouse --user

CODE:

import keyboard
import mouse
import time
import itertools
import inspect
import sys

class CB:
    """
    `CB` stands for `callback`
    """
    def __init__(self, func):
        assert(callable(func))
        self._func = func
        self._hooks = list()

    def set_args(self, *args, **kwargs):
        self._args = args
        self._kwargs = kwargs

    def hook(self, callback):
        self._hooks.append(callback)

    def __call__(self):
        r = self._func(*self._args, **self._kwargs)
        for callback in self._hooks:
            callback(self._func, self._args, self._kwargs)
        return r
# END CLASS

class LoggingCB: 
    """
    Logging callback
    """
    file = sys.stdout

    def __init__(self, func, *args, **kwargs):
        self._func = CB(func)
        self._func.set_args(*args, **kwargs)
        self._func.hook(type(self).pprint_event)

    def __call__(self):
        return self._func()

    @classmethod
    def pprint_event(cls, func, args, kwargs):
        cigar = "No signature"
        try:
            cigar = inspect.signature(func)
            cigar = cigar.bind(args, kwargs)
            print(cigar, file=cls.file)
        except ValueError:
            # no signature found for builtin <built-in function>
            sargs = list()
            safe_types = (float, int, str, bool)
            for arg in args:
                if type(arg) in safe_types:
                    sarg = str(arg)
                else:
                    sarg = object.__repr__(arg)
                sargs.append(sarg)
            print(func.__name__, sargs, file=cls.file)
# END CLASS


TDSF = 0.1 # time-delay scale factor

ctrl_presser = LoggingCB(keyboard.press_and_release, "ctrl")

delay_15 = LoggingCB(time.sleep, TDSF*15)

right_mouse_tapper = LoggingCB(mouse.right_click)

delay_150 = LoggingCB(time.sleep, TDSF * 150)

right_mouse_hold = LoggingCB(mouse.hold, button='right')

delay_5 = LoggingCB(time.sleep, TDSF*5)

right_mouse_release = LoggingCB(mouse.release, button='right')

########################################################################

class KeyboardSmasher:
    def __init__(self):
        self._go_hk = keyboard.add_hotkey('e', self.unpause)
        keyboard.add_hotkey('y', self.toggle)
        keyboard.add_hotkey('x', sys.exit)
        self.pause()
    IT_1 = [
        ctrl_presser,
        delay_15,
        right_mouse_tapper,
        delay_150,
        right_mouse_hold,
        delay_5,
        right_mouse_release
    ]
    IT_2 = [
        LoggingCB(time.sleep, 1)
    ]
    def go(self):
        for func in self._it:
            func()

    def toggle(self):
        """
        switch between `paused` and `unpaused` states
        """
        if self._state == "paused":
            self.unpause()
        else:
            self.pause()

    def unpause(self):
        self._it = itertools.cycle(type(self).IT_1)
        self._state = "unpaused"

    def pause(self):
        self._it = itertools.cycle(type(self).IT_2)
        self._state = "paused"

########################################################################

ks = KeyboardSmasher()
ks.go()
python python-3.x mouseevent mouse keyboard-events
1个回答
0
投票

我添加了print('toggle')print('unpaused')以查看它们是否已执行并且它们不显示文本。

当我删除带有sys.exit的行时,我可以看到文本。

如果我创建运行self.exit并使用sys.exit()add_hotkey('x', self.exit),那么我仍然可以看到文本。


[另一个问题是,即使代码为for func in self._it:分配了不同的迭代器,_it也始终使用首次迭代器self._it。暂停/未暂停的设置break

时,我使用self.change_it = True退出此循环
    def go(self):
        while True:
            for func in self._it:
                func()
                if self.change_it:
                    break
            self.change_it = False

    def unpause(self):
        print('unpaused')
        self._it = itertools.cycle(type(self).IT_1)
        self._state = "unpaused"
        self.change_it = True

    def pause(self):
        print('paused')
        self._it = itertools.cycle(type(self).IT_2)
        self._state = "paused"
        self.change_it = True

sys.exit()也会出现问题,它会停止侦听器,并且xye会停止工作,但不会停止循环for func in self._it:,并且会一直工作。我在上一个while run_loop:中使用while True代替了go(),所以我可以使用self.run_loop = Falseself.change_it = True]退出此循环

    def go(self):
        self.run_loop = True
        while self.run_loop:
            for func in self._it:
                func()
                if self.change_it:
                    break
            self.change_it = False

    def exit(self):
        print('exit')
        self.run_loop = False
        self.change_it = True
        sys.exit()

另一个问题是您在某些***中忘记了*args**kwargs


import keyboard
import mouse
import time
import itertools
import inspect
import sys

class CB:
    """
    `CB` stands for `callback`
    """
    def __init__(self, func):
        assert(callable(func))
        self._func = func
        self._hooks = list()

    def set_args(self, *args, **kwargs):
        self._args = args
        self._kwargs = kwargs

    def hook(self, callback):
        self._hooks.append(callback)

    def __call__(self):
        r = self._func(*self._args, **self._kwargs)
        for callback in self._hooks:
            callback(self._func, *self._args, **self._kwargs) # * **
        return r
# END CLASS

class LoggingCB: 
    """
    Logging callback
    """
    file = sys.stdout

    def __init__(self, func, *args, **kwargs):
        self._func = CB(func)
        self._func.set_args(*args, **kwargs)
        self._func.hook(type(self).pprint_event)

    def __call__(self):
        return self._func()

    @classmethod
    def pprint_event(cls, func, *args, **kwargs):  # * **
        cigar = "No signature"
        try:
            cigar = inspect.signature(func)
            cigar = cigar.bind(*args, **kwargs)  # * **
            print(cigar, file=cls.file)
        except ValueError:
            # no signature found for builtin <built-in function>
            sargs = list()
            safe_types = (float, int, str, bool)
            for arg in args:
                if type(arg) in safe_types:
                    sarg = str(arg)
                else:
                    sarg = object.__repr__(arg)
                sargs.append(sarg)
            print(func.__name__, sargs, file=cls.file)
# END CLASS


TDSF = 0.1 # time-delay scale factor

ctrl_presser = LoggingCB(keyboard.press_and_release, "ctrl")

delay_15 = LoggingCB(time.sleep, TDSF*15)

right_mouse_tapper = LoggingCB(mouse.right_click)

delay_150 = LoggingCB(time.sleep, TDSF * 150)

right_mouse_hold = LoggingCB(mouse.hold, button='right')

delay_5 = LoggingCB(time.sleep, TDSF*5)

right_mouse_release = LoggingCB(mouse.release, button='right')

########################################################################

class KeyboardSmasher:
    def __init__(self):
        self._go_hk = keyboard.add_hotkey('e', self.unpause)
        keyboard.add_hotkey('y', self.toggle)
        keyboard.add_hotkey('x', self.exit)
        self.change_it = False
        self.pause()

    IT_1 = [
        ctrl_presser,
        delay_15,
        right_mouse_tapper,
        delay_150,
        right_mouse_hold,
        delay_5,
        right_mouse_release
    ]
    IT_2 = [
        LoggingCB(time.sleep, 1)
    ]
    def go(self):
        self.run_loop = True
        while self.run_loop:
            for func in self._it:
                func()
                if self.change_it:
                    break
            self.change_it = False

    def exit(self):
        print('exit')
        self.run_loop = False
        self.change_it = True
        sys.exit()

    def toggle(self):
        """
        switch between `paused` and `unpaused` states
        """
        print('toggle')
        if self._state == "paused":
            self.unpause()
        else:
            self.pause()

    def unpause(self):
        print('unpaused')
        self._it = itertools.cycle(type(self).IT_1)
        self._state = "unpaused"
        self.change_it = True

    def pause(self):
        print('paused')
        self._it = itertools.cycle(type(self).IT_2)
        self._state = "paused"
        self.change_it = True

########################################################################

ks = KeyboardSmasher()
ks.go()
© www.soinside.com 2019 - 2024. All rights reserved.