簡體   English   中英

如何檢測 Python 進程中的按鍵?

[英]How to detect a pressed key within Python Process?

通過一個簡單的示例,我嘗試演示具有兩個進程的典型多處理設置:

  1. 接收數據(這里通過隨機數組生成模擬)
  2. 發送數據

我想通過鍵盤按鍵終止第一個進程,這會將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM