【问题标题】:Python multiprocessing shared variablesPython 多处理共享变量
【发布时间】:2020-06-12 03:02:45
【问题描述】:

我正在尝试与我在其中启动的其他进程共享类实例/对象变量,因为我需要同时运行多个函数,以从键盘和鼠标记录宏并在以后重新播放它们同一时间。

我发现可以使用 multiprocessing.Manager,但我使用的是 concurrent.futures.ThreadPoolExecutor。有没有类似的功能?

我现在写了下面的代码来澄清一下。实际代码中有一个 setState 函数用于设置录制状态等,并且按下的键不会被传递。此外,实际代码显然有一个按键和鼠标移动的侦听器,getKey 和 getMove 函数应该是附加到列表的函数。在这种情况下的问题是,一旦按下“插入”键,就不能从应该开始记录移动的第二个进程访问记录变量。一个类似于多处理中的管理器的并发函数可以解决它,但我不确定它被称为什么或使用它。

from concurrent.futures import ThreadPoolExecutor as Executor
import time

class recMacros(object):
    def __init__(self):
        self.recording = False

        self.lastKey = None
        self.lastMove = None

        self.mouseMoves = []
        self.keyPresses = []

        self.runMacros()


    def getTime(self):
        return time.time()

    def getKey(self):
        #return keyboard listener last key pressed
        return "W"

    def getMove(self):
        #return keyboard listener last key pressed
        return "W"

    def recMoves(self): 
        while True:
            while self.recording:
                mouseMove = self.getMove()
                if mouseMove != self.lastMove:
                    self.mouseMoves.append((mouseMove, self.getTime()))
                    self.lastMove = mouseMove

    def recPresses(self):
         while True:
             keyPress = self.getKey()
             if keyPress == "Insert":
                self.recording = True
             elif keyPress == "End":
                self.recording = False
             elif self.recording and keyPress != self.lastKey:
                self.keyPresses.append((keyPress, self.getTime()))
                self.lastKey = keyPress
             else:
                 print("Error")

    def recMacros(self):
        with Executor(max_workers=2) as e:
            e.submit(recPresses)
            e.submit(recMoves)

if __name__ == "__main__":
     recMacros()

我很感激一些快速的方向,因为我很着急。提前致谢

@user2357112 支持莫妮卡 这是我用来测试时间的代码,以验证 ThreadPoolExecutor 就像一个进程来并行运行函数:

from concurrent.futures import ThreadPoolExecutor
import time

def printTime():
    print(f"Time: {time.time()}\n")


def runPro():
    with ThreadPoolExecutor(max_workers=3) as e:
        for i in range(3):
            e.submit(printTime)


runPro()

【问题讨论】:

  • concurrent.futures.ThreadPoolExecutor 不是多处理。区别非常重要 - 尽管multiprocessing 试图使其界面看起来像threading,但使用单独进程的行为与使用线程的行为非常不同。
  • 谢谢。我确实怀疑它是一个多线程库而不是多处理库,但是当我测试它时,多个函数同时运行,这正是我所需要的。无论如何,当我测试它时,变量没有被共享,这意味着地址空间不同,就像它是一个进程一样。像管理这样的解决方案将不胜感激,我的日程安排很紧。我将我用来测试时间的代码添加到线程中,因为它使评论超出限制,无法在这里添加。
  • 不,ThreadPoolExecutor 不对地址空间做任何事情。如果看起来你有一个单独的地址空间,那么你真正拥有的是一个错误。
  • 有道理,它被称为“ThreadPoolExecutor”是有原因的。需要明确的是,变量值不会在其他线程中更新,这可能是什么错误?我将 self.recording 的等效值更新为 False 并且它没有改变。
  • 我们无法确定,因为您发布的代码不会重现问题。 (您发布的代码因完全不同的原因而失败。)如果我们有 minimal reproducible example,我们也许能够识别出错误。

标签: python parallel-processing macros multiprocessing concurrent.futures


【解决方案1】:

如果您想将某些内容保存在每个进程都可以使用的变量中,您可以使用queue

  1. 导入queue
import queue
  1. 创建共享变量
shared_var = queue.Queue(maxsize=0)

其中maxsize 是此队列中可以保存的最大值

  1. 在任何进程中编辑共享变量
shared_var.put(item)
  1. 获取变量中的东西
variable = shared_var.get()

您可以使用queue 做更多事情,请参阅documentation

【讨论】:

  • 感谢您抽出宝贵时间回复。我已经更新了问题,之前没有完成。我熟悉队列,有一个内置于并发中,但我正在寻找更好的解决方案。管理似乎是个不错的选择,并发中没有类似的吗?
  • 对不起,我应该删除答案吗?
  • 不需要,没关系,别人会觉得有帮助的。
猜你喜欢
  • 1970-01-01
  • 2013-06-26
  • 1970-01-01
  • 2019-12-11
  • 2015-06-08
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
  • 2021-09-23
相关资源
最近更新 更多