如何在单独的运行过程中修改类变量?

时间:2018-12-31 11:47:55

标签: python timer multiprocessing instance instance-variables

我正在尝试编写一个Python类方法,该方法执行固定的时间,并在执行过程中根据需要修改类实例变量。 对于我的项目,我需要以下代码中的read_key方法才能准确运行5秒钟(不多也不少)。

在这5秒钟内,我使用getch.getch()尝试阅读 键盘上的一个字符,并将其分配给实例变量self.key。因为getch.getch()将阻塞其过程的执行,直到检测到击键。如果用户在这5秒钟的窗口中没有按任何键,则将self.key设为None

到目前为止,我只能想到使用multiprocessing及其join()来实现这5秒钟的“计时器”效果。

import getch
import multiprocessing

class A:

    def __init__(self):
        self.key = None
        self.read_key()

        # to check whether instance variable is successfully modified
        print(self.key)     

    def read_key(self):
        def scan():
            self.key = None
            while True:     
                key = getch.getch()
                if key == 'a':
                    self.key = key
                    print('updated self key to ' + str(self.key))
                else:
                    print('invalid entry ' + str(key))
        p = multiprocessing.Process(target=scan)
        p.start()
        p.join(5)
        p.terminate()


if __name__ == '__main__':
    A()

运行上面的代码,需要5秒钟才能完成。如果用户在程序启动后按 a 键,则希望打印输出为:

'updated self key to a'
'a'

我实际上看到的是

'updated self key to a'
None

显然,即使执行了self.key = key,实际的实例变量self.key也是如此。是否知道如果用户按下 a 键,为什么以及如何修改self.key

1 个答案:

答案 0 :(得分:1)

我设法使用multiprocessing的共享变量提出了以下解决方案。使用共享变量detected,我可以检测用户是否按下了我想检测的任何特殊键。然后,我在方法末尾手动设置了类实例变量,以实现在5秒钟内设置self.key属性的效果。

https://docs.python.org/2/library/multiprocessing.html#multiprocessing.Value

def read_key(self):
    def scan(detected):
        while True:
            key = getch.getch()
            if key == 'a':
                detected.value = b'a'
            elif key == 'd':
                detected.value = b'd'
            elif key == 'w':
                detected.value = b'w'
            elif key == 's':
                detected.value = b's'

    detected = Value('c', b'z')
    p = Process(target=scan, args=(detected,))
    p.start()
    p.join(self.time_interval)
    p.terminate()
    byte_str_map = {b'a': 'a',
                    b's': 's',
                    b'w': 'w',
                    b'd': 'd'}
    self.key = byte_str_map.get(detected.value)