我想要一个满足以下要求的程序:
x
终止程序y
暂停或取消暂停程序keyboard.add_hotkey('y',self.toggle)keyboard.add_hotkey('x',sys.exit)
本文最后是我到目前为止的代码。当前,
可以像这样安装第三方库keyboard
和mouse
:
[path to python]\Python38-32\python.exe -m pip install keyboard --user
[path to python]\Python38-32\python.exe -m pip install mouse --user
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()
我添加了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()也会出现问题,它会停止侦听器,并且x
,y
,e
会停止工作,但不会停止循环for func in self._it:
,并且会一直工作。我在上一个while run_loop:
中使用while True
代替了go()
,所以我可以使用self.run_loop = False
和self.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()