【问题标题】:Shared memory global list while running multiprocessing in python在 python 中运行多处理时共享内存全局列表
【发布时间】:2021-02-22 05:09:24
【问题描述】:

我目前正在为我的流媒体编写一个聊天机器人。由于它需要一次执行多项操作,因此我正在使用多处理模块,这样它仍然可以同时响应命令并执行功能。我现在的问题是我有一个进程专门用于一些网络抓取,而另一个进程用于查看聊天并在键入命令时做出响应。我的想法是,如果我将来自一个进程的信息附加到全局列表中,然后在聊天中键入命令时,另一个进程可以使用附加列表中的信息。好吧,这没有用,我了解到这是因为这两个进程没有共享内存,虽然它们都可以访问同一个列表,但它们都是列表的副本,所以即使一个附加到另一个处理'的情况下,它仍然是空的。我在这里遇到了一些关于堆栈溢出的问题,但是这些示例非常具体,而且由于我对编码还很陌生,所以我很难弄清楚如何将它应用到我自己的代码中。出于这个确切的原因,我已经简化了问题,以便它可以帮助处于类似情况的其他人,通过让我的示例足够广泛和简单,以便任何人在阅读解决方案后都能理解它。因此,这不是我实际用于聊天机器人的代码,而是模仿问题的代码。

import multiprocessing as mp
import time

globalList = []

def readList():
    while True:
        time.sleep(2)
        if globalList:
            print(globalList)
        else:
            print("List is Empty")
            print(globalList)
def writeList():
    while True:
        time.sleep(3)
        globalList.append("Item")
        print(globalList)

if __name__ == '__main__':
    p1 = mp.Process(target=readList)
    p2 = mp.Process(target=writeList)
    p1.start()
    p2.start()

运行此代码时,您可以看到 writeList 函数会不断向列表中添加另一个项目,但 readList 函数会一直显示一个空列表。

我希望那里的一些大师可以帮助我解决这个问题。

【问题讨论】:

    标签: python multiprocessing global-variables shared-memory


    【解决方案1】:

    Pythonprocesses cannot 中直接访问由其他进程创建的全局可变对象。为此,您可以使用例如multiprocessing.Manager 及其代理对象。你改编的例子:

    import multiprocessing as mp
    import time
    
    
    def readList(shared_list):
        while True:
            time.sleep(2)
            if shared_list:
                print(shared_list)
            else:
                print("List is Empty")
                print(shared_list)
    
    
    def writeList(shared_list):
        while True:
            time.sleep(3)
            shared_list.append("Item")
            print(shared_list)
    
    
    if __name__ == '__main__':
        manager = mp.Manager()
        shared_list = manager.list()
        p1 = mp.Process(target=readList, args=(shared_list,))
        p2 = mp.Process(target=writeList, args=(shared_list,))
        p1.start()
        p2.start()
        p1.join()
        p2.join()
    

    【讨论】:

    • 感谢您的意见。它起作用了,很高兴你进来并提出你的意见,否则我会认为这是不可能的。现在它适用于示例,我将尝试将其应用到我的真实代码中。
    • 我坐在这里修修补补,这让我开始思考,我可以只有一个这样的列表吗?或者 python 会理解让我们说 list2 = manager.list() 不是前一个列表的新命名吗?
    • list2 将是新列表,而不是前一个列表的链接
    【解决方案2】:

    你不能通过正常的方式拥有它。进程有自己的内存空间。另一方面,线程具有相同的内存空间并在一个进程中运行。

    更多信息,请参考这个答案Multiprocessing vs Threading Python

    【讨论】:

    • 您好感谢您的回答,据我了解,线程的工作方式与 asyncio 非常相似,这意味着它在其他函数等待时工作。如果您不需要一个函数来连续运行,那就太好了,不幸的是我需要这个。由于脚本的聊天部分需要接收和回答传入的聊天提要,而另一个函数有时会在等待下一个函数取而代之之前工作 5 分钟。所以我的意思是,你说它不能通过“正常方式”来完成,那么实现它的不规则方式是什么? :P
    • @Benji 我会试着总结一下。线程用于 IO 密集型任务,多处理用于 CPU 密集型任务。如果您的应用程序被冻结,因为对天气 API 的请求很长 - 使用线程。如果您进行大量 CPU 密集型计算 - 使用多处理。不规则的方法是使用某种外部存储来保存公共数据。究竟是哪个 - 我不知道,这只是我脑海中的一个概念。
    • 谢谢@go2nirvana,我会尝试研究一下,看看我能不能让它发挥作用。
    猜你喜欢
    • 2016-11-14
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 2017-01-02
    • 2013-08-19
    • 2012-12-16
    相关资源
    最近更新 更多