在多个python进程之间交换基于击键的数据

2024-06-16 12:33:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我在脚本中运行两个独立的进程。第一个进程p1启动一个oneSecondTimer例程,该例程恰好在1秒执行并执行一些工作。第二个进程p2发出一个键盘监听器,好吧,监听键盘。在

目前,我希望p1进程在用户按下escape键时停止。我试着用一个全局变量,但没用。我试着用一个队列,它成功了,但它绝对不是最优雅的解决方案。这实际上是一个丑陋的解决办法,不会扩大规模。在

最终,脚本将有许多单独的并行进程,这些进程将通过按不同的键来控制(而不仅仅是启动/停止)。 这是密码

import time
from pynput import keyboard
from multiprocessing import Process, Queue


def on_release(key):
    if key == keyboard.Key.esc:
        print('escaped!')
        # Stop listener
        return False


def keyboardListener(q):
    with keyboard.Listener(on_release=on_release) as listener:
        listener.join()
    print('Keybord Listener Terminated!!!')
    # Make the queue NOT EMPTY
    q.put('Terminate')


def oneSecondTimer(q):
    starttime = time.time()
    # Terminate the infinite loop if 
    # queue is NOT EMPTY
    while (not q.qsize()):
        print("tick")
        time.sleep(1.0 - ((time.time() - starttime) % 1.0))
    return False


if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=oneSecondTimer, args=(q,))
    p1.start()
    p2 = Process(target=keyboardListener, args=(q,))
    p2.start()

Tags: import脚本releaseiftime进程ondef
1条回答
网友
1楼 · 发布于 2024-06-16 12:33:46

终于成功了。 在上面的片段中,当我调用

listener.join()

对于Keyboard Listener事件,它实际上是在阻止剩余的keyboardListener(q)进程的执行,直到on_release(key)函数停止。因为这正是.join()应该做的。这是一个阻塞调用。在

在下面的片段中,监听器键盘线程只需在keyboardListener(q)进程中启动。一个while循环跟踪名为fetchKeyPress的变量。该变量按照名称所示的方式执行,它获取on_release(key)子例程中按下的键。fetchKeyPress获取的按键被泵入名为q的队列,该队列在两个进程中共享,即keyboardListener(Key)oneSecondTimer(q)。keyboardListener进程的运行速度是oneSecondTimer进程的4倍,它具有退出while循环的逻辑,并防止用户连续/重复按同一个键时队列的泛滥。在

oneSecondTimer(q)进程每秒运行一次。如果q不是空的,它会吐出q中的任何东西。它还内置了一个while循环出口逻辑。在

现在我可以利用由进程p2获得的数据(按键),并将其用于另一个并行运行的进程p1。在

p2生产商p1消费者。在

import time
from pynput import keyboard
from multiprocessing import Process, Queue

fetchKeyPress = 10

def on_release(key):
    global fetchKeyPress 
    fetchKeyPress = key
    if key == keyboard.Key.esc:
        fetchKeyPress = 0
        print('escaped!')
        # Stop listener
        return False


def keyboardListener(q):
    global fetchKeyPress
    prevKeyFetch = 10    # Keep track of the previous keyPress
    keyboard.Listener(on_release=on_release).start()
    while (fetchKeyPress):
        print ('Last Key Pressed was ', fetchKeyPress)
        # Fill the Queue only when a new key is pressed
        if (not (fetchKeyPress == prevKeyFetch)):
            q.put(fetchKeyPress)   
        # Update the previous keyPress
        prevKeyFetch = fetchKeyPress
        time.sleep(0.25)
    print('Keybord Listener Terminated!!!')
    q.put('Terminate')


def oneSecondTimer(q):
    runner = True   # Runs the while() loop
    starttime = time.time()
    while (runner):
        print('\ttick')
        if (not q.empty()): 
            qGet = q.get()
            print ('\tQueue Size ', q.qsize())
            print ('\tQueue out ', qGet)
            # Condition to terminate the program
            if (qGet == 'Terminate'):
                # Make runner = False to terminate the While loop
                runner = False
        time.sleep(1.0 - ((time.time() - starttime) % 1.0))
    return False


if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=oneSecondTimer, args=(q,))
    p1.start()
    p2 = Process(target=keyboardListener, args=(q,))
    p2.start()

但我认为归根结底,我可能只会使用https://pypi.org/project/keyboard/库,因为它很简单。感谢@toti08在上述评论中的建议。在

相关问题 更多 >