python - 如何正确终止 pynput 调用?现在它使我的 X 崩溃(self.socket_error)
问题描述
我正在尝试使用 pynput('pijnput' 转换为痛苦的坑:-))模块来捕获键盘。这是我的代码:
class KeyPress:
def __init__(self,parent):
self.parent=parent
def on_press(self,key):
#keyboard.Listener.stop()
try:
self.parent.pressedKey=key.char
self.parent.pressedKeyCode=None
except AttributeError:
self.parent.pressedKey=key
self.parent.pressedKeyCode=key.value.vk
return False
def on_release(self,key):
if key == keyboard.Key.esc:
# Stop listener
return False
# Collect events until released
def run(self):
with keyboard.Listener(
on_press=self.on_press,
on_release=self.on_release,suppress=True) as listener:
listener.join()
我创建了一个子类,它将键和 keyCode 分配给主类的属性如果我运行它,它可以正常工作,直到我按下一定数量的键然后 X 崩溃并出现此错误。起初我在 ipython + tmux 中运行它,但也在纯 bash 中运行,这种情况发生了。
Exception in thread Thread-131:
Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib/python3.7/site-packages/pynput/_util/__init__.py", line 136, in run
self._run()
File "/usr/lib/python3.7/site-packages/pynput/keyboard/_xorg.py", line 499, in _run
super(Listener, self)._run()
File "/usr/lib/python3.7/site-packages/pynput/_util/xorg.py", line 370, in _run
self._display_record = Xlib.display.Display()
File "/usr/lib/python3.7/site-packages/Xlib/display.py", line 89, in __init__
self.display = _BaseDisplay(display)
File "/usr/lib/python3.7/site-packages/Xlib/display.py", line 71, in __init__
protocol_display.Display.__init__(self, *args, **keys)
File "/usr/lib/python3.7/site-packages/Xlib/protocol/display.py", line 163, in __init__
auth_prot_data = auth_data)
File "/usr/lib/python3.7/site-packages/Xlib/protocol/display.py", line 1070, in __init__
display.send_and_recv(request = -1)
File "/usr/lib/python3.7/site-packages/Xlib/protocol/display.py", line 610, in send_and_recv
raise self.socket_error
Xlib.error.ConnectionClosedError: Display connection closed by server
我的猜测是我创建了太多线程,因为我没有终止它们。虽然我假设'with'构造会处理这个问题?这个对吗 ?如果是这样,我应该怎么做才能让它发挥作用?
提前致谢
解决方案
当您返回 False pynput 停止但线程仍处于打开状态时,当您返回它时,它会创建一个全新的线程并重复该过程,我将 pynput 置于一个循环中并最终得到许多线程,我在我的只有 1 个线程使用 pynput 的代码是这样的:
from pynput.keyboard import Key, Listener, Controller
listener = None
keyPressed = None
def on_press(key):
if key == Key.enter:
# here add a bolean that will detect when enter pressed
global saveFile
saveFile = True
def on_release(key):
global xPosition
global yPosition
global zPosition
# in my case I'm moving and object with the keys so if I keep my finger on it it
#keeps calling this method, you can simple have a string that is equal to key.char
#to know the pressed key from anywhere
global keyPressed
keyPressed = key.char
if key.char == ('d'):
xPosition -= 0.03
elif key.char == ('a'):
xPosition += 0.03
elif key.char == ('w'):
zPosition += 0.03
elif key.char == ('s'):
zPosition -= 0.03
elif key.char == ('q'):
yPosition += 0.03
elif key.char == ('e'):
yPosition -= 0.03
def CheckWhichKeyIsPressed():
global listener
# here is the secret, create only if it doesn't exist yet
if listener == None:
listener = Listener(on_press=on_press, on_release=on_release,suppress=True)
listener.start()
通过仅在尚未创建线程的情况下创建线程,我设法只有 1 个始终在监听,然后我使用 on_press 和 on_release 更改变量,在我的情况下,SaveFile 布尔值在使用后被关闭,所以尽快当用户再次按下回车键时,pynput 将把它捡起来,我可以保存一个新文件:
global saveFile
if saveFile:
saveFile = False
SaveFile()
有了这个 pynput 总是在听并告诉你你只用 1 个线程按下了什么键
推荐阅读
- node.js - npm-windows-upgrade 未完成
- ffmpeg - android NDK 找不到符号“mmap64”
- c++ - 套接字或 HTTP 请求
- java - DecimalFormat 未返回正确的数字
- string - Python 中的运行时错误(TypeError:无法将 'float' 对象隐式转换为 str)
- c# - 如何在c#中将texbox格式化为NIC格式
- python - 如何测试任何给定网页页脚中的所有链接
- c++ - Openmp for loop:工作不平衡的静态调度
- ruby-on-rails - 更新博客 gem 中的 jekyll 主题
- python - 获取由未知分隔符分隔的字符串中的最后一个数字