Python 线程被键盘库阻塞?
Python threading blocked by keyboard library?
正在构建可切换为垃圾邮件的脚本。我遇到了以下问题。
首先是脚本的正常运行版本:
import keyboard
import threading
def spam_this():
status = 0
while True:
if keyboard.is_pressed("F9") and status == 0:
status = 1
event.wait(1)
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
while status == 1:
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
print("test")
event = threading.Event()
threading.Thread(target=spam_this).start()
上面的脚本完美运行。但是,当我将行 print("test")
更改为 keyboard.write("test")
时。脚本中断。
import keyboard
import threading
def spam_this():
status = 0
while True:
if keyboard.is_pressed("F9") and status == 0:
status = 1
event.wait(1)
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
while status == 1:
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
keyboard.write("test")
event = threading.Event()
threading.Thread(target=spam_this).start()
具有keyboard.write()
功能的这个版本的脚本可以用隐含的切换键“F9”启动,但是当我尝试再次按下“F9”来关闭开关时,它不会停止就像它自己的 print("test")
版本。
注意:我不知道如何在标题中表达这个问题。我使用术语“阻塞”是因为效果类似于 time.sleep()
等阻塞方法在尝试创建带有切换的 while True:
循环时所做的事情。
keyboard
可能 运行 也拥有 thread
中的代码,并且两个线程之间可能存在冲突。 Python 一次只使用一个线程 GIL
到 运行 - 所以当你的线程 运行ning 时它可能会阻塞应该在屏幕上写文本的线程。如果我在 write()
之后使用 even.wait(0.1)
代码效果会更好,因此 Python 可以切换线程并在屏幕上发送文本。如果你使用更长的值那么它也可以工作但是如果你按键非常快那么它可能仍然 运行 write
或 wait
并且它无法检查 is_pressed("F9")
并且不会停止它 - 如果你在 write
之后使用 event.wait(1)
你应该会看到它
还有其他问题 - 它可能会在按下 key 后写最后一个文本,它应该使用 break
退出 while
并跳过 write
import threading
import keyboard
def spam_this():
status = 0
while True:
if keyboard.is_pressed("F9") and status == 0:
status = 1
event.wait(1)
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
while status == 1:
if keyboard.is_pressed("F9") and status == 1:
print('stop')
status = 0
event.wait(1)
break
keyboard.write("test")
event.wait(0.1)
event = threading.Event()
threading.Thread(target=spam_this).start()
但我会减少到
import threading
import keyboard
def spam_this():
print('start spam_this')
status = False
while True:
if keyboard.is_pressed("F9"):
status = not status
print('status:', status)
event.wait(0.1)
if status is True:
keyboard.write("test")
event.wait(0.1)
event = threading.Event()
threading.Thread(target=spam_this).start()
但它还有另一个问题——如果你按住按键的时间更长,那么它会切换status
很多次。我添加了 print('status:', status)
来显示它。
我想像这样使用 keyboard.add_hotkey
import threading
import keyboard
# global variable
status = False
def spam_this():
print('start: spam_this')
while True:
if status is True:
keyboard.write("test")
event.wait(0.1)
def test():
global status
status = not status
print('change:', status)
event.wait(0.5)
event = threading.Event()
threading.Thread(target=spam_this).start()
keyboard.add_hotkey("F9", test)
keyboard.wait()
但是当您按住该键时,系统可能会再次开始发送相同的键。
我没有测试 keyboard.on_press_key()
- 也许它会解决它。
文档:keyboard
import threading
import keyboard
# global variable
status = False
def spam_this():
print('start: spam_this')
while True:
if status is True:
print("test")
keyboard.write("test")
event.wait(0.1)
def test(event=None):
global status
status = not status
print('change:', status)
event = threading.Event()
keyboard.add_hotkey("F9", test)
#alternatively:
#keyboard.on_key_press("F9", test)
threading.Thread(target=spam_this).start()
对@furas 的回答进行了一些修改。
为test
函数添加了一个参数event=None
,否则keyboard.on_press_key
会将F9
按键事件传递给测试函数,结果为 typeError
.
在test
函数中,由于错误删除了event.wait()
,经测试,keyboard.on_press_key
和keyboard.add_hotkey
函数确实有内置延迟,所以只要 F9
键没有被按住,内置延迟就足够了。
无论使用on_key_press
还是add_hotkey
,都应该在调用所需的“热键方法”后初始化线程。否则线程将阻塞 python 脚本的主循环。(这部分我无法解释为什么,这只是导致这个结论的反复试验。)
删除了 keyboard.wait()
,因为没有使用此功能。
数字 1 和数字 3 是最重要的变化
(对于不想通读次要部分的人)
正在构建可切换为垃圾邮件的脚本。我遇到了以下问题。 首先是脚本的正常运行版本:
import keyboard
import threading
def spam_this():
status = 0
while True:
if keyboard.is_pressed("F9") and status == 0:
status = 1
event.wait(1)
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
while status == 1:
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
print("test")
event = threading.Event()
threading.Thread(target=spam_this).start()
上面的脚本完美运行。但是,当我将行 print("test")
更改为 keyboard.write("test")
时。脚本中断。
import keyboard
import threading
def spam_this():
status = 0
while True:
if keyboard.is_pressed("F9") and status == 0:
status = 1
event.wait(1)
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
while status == 1:
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
keyboard.write("test")
event = threading.Event()
threading.Thread(target=spam_this).start()
具有keyboard.write()
功能的这个版本的脚本可以用隐含的切换键“F9”启动,但是当我尝试再次按下“F9”来关闭开关时,它不会停止就像它自己的 print("test")
版本。
注意:我不知道如何在标题中表达这个问题。我使用术语“阻塞”是因为效果类似于 time.sleep()
等阻塞方法在尝试创建带有切换的 while True:
循环时所做的事情。
keyboard
可能 运行 也拥有 thread
中的代码,并且两个线程之间可能存在冲突。 Python 一次只使用一个线程 GIL
到 运行 - 所以当你的线程 运行ning 时它可能会阻塞应该在屏幕上写文本的线程。如果我在 write()
之后使用 even.wait(0.1)
代码效果会更好,因此 Python 可以切换线程并在屏幕上发送文本。如果你使用更长的值那么它也可以工作但是如果你按键非常快那么它可能仍然 运行 write
或 wait
并且它无法检查 is_pressed("F9")
并且不会停止它 - 如果你在 write
event.wait(1)
你应该会看到它
还有其他问题 - 它可能会在按下 key 后写最后一个文本,它应该使用 break
退出 while
并跳过 write
import threading
import keyboard
def spam_this():
status = 0
while True:
if keyboard.is_pressed("F9") and status == 0:
status = 1
event.wait(1)
if keyboard.is_pressed("F9") and status == 1:
status = 0
event.wait(1)
while status == 1:
if keyboard.is_pressed("F9") and status == 1:
print('stop')
status = 0
event.wait(1)
break
keyboard.write("test")
event.wait(0.1)
event = threading.Event()
threading.Thread(target=spam_this).start()
但我会减少到
import threading
import keyboard
def spam_this():
print('start spam_this')
status = False
while True:
if keyboard.is_pressed("F9"):
status = not status
print('status:', status)
event.wait(0.1)
if status is True:
keyboard.write("test")
event.wait(0.1)
event = threading.Event()
threading.Thread(target=spam_this).start()
但它还有另一个问题——如果你按住按键的时间更长,那么它会切换status
很多次。我添加了 print('status:', status)
来显示它。
我想像这样使用 keyboard.add_hotkey
import threading
import keyboard
# global variable
status = False
def spam_this():
print('start: spam_this')
while True:
if status is True:
keyboard.write("test")
event.wait(0.1)
def test():
global status
status = not status
print('change:', status)
event.wait(0.5)
event = threading.Event()
threading.Thread(target=spam_this).start()
keyboard.add_hotkey("F9", test)
keyboard.wait()
但是当您按住该键时,系统可能会再次开始发送相同的键。
我没有测试 keyboard.on_press_key()
- 也许它会解决它。
文档:keyboard
import threading
import keyboard
# global variable
status = False
def spam_this():
print('start: spam_this')
while True:
if status is True:
print("test")
keyboard.write("test")
event.wait(0.1)
def test(event=None):
global status
status = not status
print('change:', status)
event = threading.Event()
keyboard.add_hotkey("F9", test)
#alternatively:
#keyboard.on_key_press("F9", test)
threading.Thread(target=spam_this).start()
对@furas 的回答进行了一些修改。
为
test
函数添加了一个参数event=None
,否则keyboard.on_press_key
会将F9
按键事件传递给测试函数,结果为typeError
.在
test
函数中,由于错误删除了event.wait()
,经测试,keyboard.on_press_key
和keyboard.add_hotkey
函数确实有内置延迟,所以只要F9
键没有被按住,内置延迟就足够了。无论使用
on_key_press
还是add_hotkey
,都应该在调用所需的“热键方法”后初始化线程。否则线程将阻塞 python 脚本的主循环。(这部分我无法解释为什么,这只是导致这个结论的反复试验。)删除了
keyboard.wait()
,因为没有使用此功能。
数字 1 和数字 3 是最重要的变化 (对于不想通读次要部分的人)