我写了这段代码来观察keydown动作的事件。问题似乎是当运行此脚本时,某些程序将使此程序崩溃,并吐出此错误消息:
TypeError: KeyboardSwitch() missing 8 required positional arguments: 'msg', 'vk_
code', 'scan_code', 'ascii', 'flags', 'time', 'hwnd', and 'win_name'
一些观察到崩溃的程序是:Skype,Sublime Text 2
经过几次试验调试后,问题似乎发生在最后一行,但我似乎无法缩小范围。我也不理解编译器返回的KeyboardSwitch()的含义......
我还发现该程序会交替返回此错误消息
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\pyHook\HookManager.py", line 351, in KeyboardSwitch
return func(event)
File "observe.py", line 6, in OnKeyboardEvent
print ('MessageName:',event.MessageName)
TypeError: an integer is required (got type NoneType)
原因是什么以及如何解决这个问题,特别是因为它只出现在按下的两个键中只有一个
import pyHook, pythoncom
def OnKeyboardEvent(event):
# Source: http://code.activestate.com/recipes/553270-using-pyhook-to-block-windows-keys/
print ('MessageName:',event.MessageName)
print ('Message:',event.Message)
print ('Time:',event.Time)
print ('Window:',event.Window)
print ('WindowName:',event.WindowName)
print ('Ascii:', event.Ascii, chr(event.Ascii))
print ('Key:', event.Key)
print ('KeyID:', event.KeyID)
print ('ScanCode:', event.ScanCode)
print ('Extended:', event.Extended)
print ('Injected:', event.Injected)
print ('Alt', event.Alt)
print ('Transition', event.Transition)
print ('---')
hooks_manager = pyHook.HookManager()
hooks_manager.KeyDown = OnKeyboardEvent
hooks_manager.HookKeyboard()
pythoncom.PumpMessages()
P.S。作为初学者,我对pythoncom的功能并不十分熟悉,在线定义似乎相当含糊。关于pythoncom和PumpMessages功能的解释将不胜感激。
由于
答案 0 :(得分:8)
我认为问题在于,当Windows调用pyHook时,它首先要做的是获取焦点窗口的窗口名称。
PSTR win_name = NULL;
...
// grab the window name if possible
win_len = GetWindowTextLength(hwnd);
if(win_len > 0) {
win_name = (PSTR) malloc(sizeof(char) * win_len + 1);
GetWindowText(hwnd, win_name, win_len + 1);
}
所以我认为这里的问题是,即使GetWindowText
没有返回宽字符,它也可以从ANSI代码页返回非ascii字符。但是,在我们这样做之前,这不会失败:
// pass the message on to the Python function
arglist = Py_BuildValue("(iiiiiiiz)", wParam, kbd->vkCode, kbd->scanCode, ascii,
kbd->flags, kbd->time, hwnd, win_name);
这里,由于格式字符串中的z
,win_name
变量中的数据正在转换为带str
的unicode Py_BuildValue
,假设它是ASCII。但事实并非如此:因此它可以触发UnicodeDecodeError
。这会导致arglist
为NULL
,因此您的函数将被调用而不带参数。
所以我不确定这里最好的解决方案。但我只是改变了两个代码来使用宽字符和unicode而不是ascii,并重建了pyHook,这似乎解决了它。我认为它只适用于Python 3版本,但对于Python 2,我认为旧的pyHook仍然有效。
LPWSTR win_name = NULL;
...
// grab the window name if possible
win_len = GetWindowTextLengthW(hwnd);
if(win_len > 0) {
win_name = (LPWSTR) malloc(sizeof(wchar_t) * win_len + 1);
GetWindowTextW(hwnd, win_name, win_len + 1);
}
和
// pass the message on to the Python function
arglist = Py_BuildValue("(iiiiiiiu)", wParam, kbd->vkCode, kbd->scanCode, ascii,
kbd->flags, kbd->time, hwnd, win_name);
只有在标题中包含非ascii字符的窗口才会出现问题:Skype是一个。
答案 1 :(得分:0)
如果每2个印刷机中只有1个有效,那么肯定是缺少返回值的问题。尝试返回True或False。
答案 2 :(得分:0)
python3有一个pyhook:https://github.com/Answeror/pyhook_py3k 此错误已在此项目中修复。