[英]How to detect a pressed key within Python Process?
通過一個簡單的示例,我嘗試演示具有兩個進程的典型多處理設置:
我想通過鍵盤按鍵終止第一個進程,這會將None
發送到隊列,然后停止程序。 我使用鍵盤包來檢測是否按下了某個鍵。
import multiprocessing
import keyboard
import numpy as np
def getData(queue):
KEY_PRESSED = False
while KEY_PRESSED is False:
if keyboard.is_pressed("a"):
queue.put(None)
print("STOP in getData")
KEY_PRESSED=True
else:
data = np.random.random([8, 250])
queue.put(data)
def processData(queue):
FLAG_STOP = False
while FLAG_STOP is False:
data = queue.get() # # ch, samples
if data is None:
print("STOP in processData")
FLAG_STOP = True
else:
print("Processing Data")
print(str(data[0,0]))
if __name__ == "__main__":
queue = multiprocessing.Queue()
processes = [
multiprocessing.Process(target=getData, args=(queue,)),
multiprocessing.Process(target=processData, args=(queue,))
]
for p in processes:
p.start()
for p in processes:
p.join()
如果我調試代碼,實際上會檢測到按下的鍵,但同時將來自 while 循環的隨機數據放入隊列中。 這使得調試代碼變得非常困難。
此外,我嘗試了pynput包,它創建了一個線程來檢測按下的鍵。 使用這種方法但是發生了同樣的問題,程序並沒有通過向其他進程發送None
來安全地終止執行。
如果有人可以指出所描述方法中的錯誤,或者提出另一種方法來安全地檢測進程中的按鍵,我會非常高興。
我不確定你在描述什么問題: savely不是一個英語單詞。 您說實際檢測到按下的鍵。 如果是這種情況,並且如果您在兩個函數中都有print("STOP...")
語句,那么如果您只是從命令提示符運行代碼並且getData
檢測到a
被按下,那么我看不到如何最終不會執行兩個打印語句並且兩個進程終止。
如果問題是程序在很長一段時間內沒有終止,那么我認為您缺少的是除非對keyboard.is_pressed("a")
的調用是一個執行起來特別慢的函數,否則到時候您會繞過按下鍵盤上的a
,函數getData
在寫入None
之前已經將數千條記錄寫入隊列。 這意味着processData
必須首先讀取那數千條記錄並打印它們,然后才能最終到達None
記錄。 由於它還必須打印數字,因此processData
無法跟上getData
。 在getData
寫入其None
記錄后很長時間, processData
仍有數千條記錄要讀取。
這可以在您的代碼變體中得到證明,其中函數getData
不等待鍵盤輸入,而是在寫入其None
記錄和終止之前簡單地將隨機數寫入輸出隊列 5 秒鍾(這模擬您的程序,在按下之前等待 5 秒鍾a
)。 函數processData
打印它在到達None
記錄之前已讀取的記錄數以及讀取和打印這些記錄所用的時間:
import multiprocessing
import numpy as np
import time
def getData(queue):
KEY_PRESSED = False
expiration = time.time() + 5
# Run for 5 seconds:
while KEY_PRESSED is False:
if time.time() > expiration:
queue.put(None)
print("STOP in getData")
KEY_PRESSED=True
else:
data = np.random.random([8, 250])
queue.put(data)
def processData(queue):
FLAG_STOP = False
t = time.time()
cnt = 0
while FLAG_STOP is False:
data = queue.get() # # ch, samples
if data is None:
print("STOP in processData")
print('Number of items read from queue:', cnt, 'elapsed_time:', time.time() - t)
FLAG_STOP = True
else:
cnt += 1
print("Processing Data")
print(str(data[0,0]))
if __name__ == "__main__":
queue = multiprocessing.Queue()
processes = [
multiprocessing.Process(target=getData, args=(queue,)),
multiprocessing.Process(target=processData, args=(queue,))
]
for p in processes:
p.start()
for p in processes:
p.join()
印刷:
...
Processing Data
0.21449036510257957
Processing Data
0.27058883046461824
Processing Data
0.5433716680659376
STOP in processData
Number of items read from queue: 128774 elapsed_time: 35.389172077178955
即使getData
只寫了 5 秒的數字, processData
讀取和打印它們也需要 35 秒。
該問題可以通過限制 Queue 實例上的消息數量來解決:
queue = multiprocessing.Queue(1)
這將阻止getData
將下一個值放入隊列,直到processData
讀取該值。
印刷:
...
Processing Data
0.02822635996071321
Processing Data
0.05390434023333657
Processing Data
STOP in getData
0.9030600225686444
STOP in processData
Number of items read from queue: 16342 elapsed_time: 5.000030040740967
因此,如果您使用maxsize為 1 的隊列,您的程序應在按下a
鍵后立即終止。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.