Python 在多处理时保留类实例列表内容

Python 在多处理时保留类实例列表内容,python,multiprocessing,Python,Multiprocessing,假设我有一门课叫狗: class dog(): def __init__(self, name, age): self.name = name self.age = age self.fleas = [] 现在让我们假设我有一张名单 names = ["bob", "joe", "dave"] 我创建一个列表,执行以下操作: dogs = [dog(name, index) for index, name in enum

假设我有一门课叫狗:

class dog():
     def __init__(self, name, age):
          self.name = name
          self.age = age
          self.fleas = []
现在让我们假设我有一张名单

names = ["bob", "joe", "dave"] 
我创建一个列表,执行以下操作:

dogs = [dog(name, index) for index, name in enumerate(names)]  # Creates a list "dogs" that has 3 dog classes in it, named bob, joe, david, with ages 0, 1, 2 respectively.
def dirty_dog(dog):
     dog.fleas.append(global_fleas[dog.name])
现在我有一本跳蚤字典

global_fleas = {"bob":[flea_43], "joe":[flea_20], "dave":[flea_3]}
还有一个单独的方法
flea\u mod()
,它修改了这个字典,使每只狗的跳蚤数变成了一个随机数,比如flea\u 50。这本字典里每只狗只有一只跳蚤

我可以通过执行以下操作将global_跳蚤中的跳蚤附加到其相应的狗:

dogs = [dog(name, index) for index, name in enumerate(names)]  # Creates a list "dogs" that has 3 dog classes in it, named bob, joe, david, with ages 0, 1, 2 respectively.
def dirty_dog(dog):
     dog.fleas.append(global_fleas[dog.name])
这是踢球的人。我想对这个循环进行多重处理。以下是我现在拥有的:

while True:
    flea_mod()  # This randomizes the flea_number for each dog in the global_flea dictionary
    pool = multiprocessing.Pool(processes=len(dogs))
    [pool.apply_async(dirty_dog, dog) for dog in dogs]
    pool.close()
    pool.join()

所以问题是,每次循环运行时,每个dog对象都不会保留其跳蚤列表。我希望每只狗的跳蚤列表保留在每个循环的末尾,这样在两个循环后,每只狗将有两个跳蚤,依此类推。有什么想法吗?我猜我得泡菜了。

J.F塞巴斯蒂安是对的。在循环中看不到突变的原因是它们发生在另一个过程中。看来你对流程不是很熟悉;你应该考虑。

你想从游泳池中获取结果,并将它们复制到你当地的狗身上。一种方法是修改循环,使其看起来像这样:

pool = multiprocessing.Pool(processes=some_number_of_processes)
while True:
    flea_mod()
    results = [pool.appy_async(dirty_dog, dog) for dog in dogs]
    for result, dog in zip(results, dogs):
        # I assume that dirty_dog returns the updated dog.
        dog.update(result.get(timeout=some_positive_number_of_seconds))
有几件事需要注意:

  • 您应该避免在每次迭代期间创建新池。这样可以避免创建进程(池)的开销
  • 一些\u个\u进程可以
    !每个进程都会产生一些开销;因此,存在一个收益递减点。通常高估一点比低估一点要好。然而,除非你真的很懒,否则高估很容易避免

  • 如果你使用Python 3.2或更高,而DurtyId狗不是CPU绑定的(例如经常触摸磁盘),那么考虑使用A代替;这样,就不需要复制修改,因为线程将在相同的对象上操作,而不是在副本上操作。

    多处理文档建议尽可能避免共享状态,但您可能可以使用托管字典来实现您的目标:

    (请参阅基于服务器的管理器部分。)

    通过这种方式,您可以根据核心逻辑更改单个托管对象,处理节点将看到更新的版本。你必须在你的代码中尝试一下,看看什么是最好的共享设置(如果有的话!)。

    除非
    dirty\u dog()
    做了一些这里没有显示的冗长计算;多处理不会提高性能(来回复制数据会消耗所有好处)


    默认情况下,进程之间不共享数据
    dirty_dog()
    (如果您正确调用它)将在子进程中处理每个狗的副本。你为什么要在这里使用多重处理?我知道Sebastian。我想做的是每次循环时都保留每只狗的跳蚤列表,这样每只狗的跳蚤列表就会变长。我只是把这些狗狗的东西编造成一个简单的类比,来说明我真正想做的事情。我真正想做的多处理将使事情进行得更快。在这个循环的每次迭代中创建一个新的池意味着每次迭代都必须产生新的进程,这会产生大量的操作系统开销。在使用流程池时,请考虑“创建一次,处理一批”。谢谢。我有一个使用管理器的代码版本,但它要复杂得多。@user2197885我的答案提供了一个更简单的(imho)解决方案。
    multiprocessing.dummy.Pool
    提供了相同的接口,但使用了线程。