使用多处理从前导和尾随遍历列表

时间:2015-05-08 20:15:28

标签: python python-2.7 concurrency multiprocessing

我想迭代一个带有2个函数的列表,使用多处理,一个函数遍历main_list,从前导和其他尾随,我希望这个函数每次遍历样本列表(g)放置元素在主列表中,直到其中一个在列表中找到重复,然后我希望终止两个进程并返回看到的元素。

我希望第一个流程返回:

['a', 'b', 'c', 'd', 'e', 'f']

第二次回归:

['l', 'k', 'j', 'i', 'h', 'g']

这是我的代码返回错误:

from multiprocessing import Process, Manager

manager = Manager()
d = manager.list()

# Fn definitions and such
def a(main_path,g,l=[]):
  for i in g:
    l.append(i)
    print 'a'
    if i in main_path:
      return l
    main_path.append(i)

def b(main_path,g,l=[]):
  for i in g:
    l.append(i)
    print 'b'
    if i in main_path:
      return l
    main_path.append(i)

g=['a','b','c','d','e','f','g','h','i','j','k','l']
g2=g[::-1]

p1 = Process(target=a, args=(d,g))
p2 = Process(target=b, args=(d,g2))
p1.start()
p2.start()

这是Traceback

a
Process Process-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "/home/bluebird/Desktop/persiantext.py", line 17, in a
    if i in main_path:
  File "<string>", line 2, in __contains__
  File "/usr/lib/python2.7/multiprocessing/managers.py", line 755, in _callmethod
    self._connect()
  File "/usr/lib/python2.7/multiprocessing/managers.py", line 742, in _connect
    conn = self._Client(self._token.address, authkey=self._authkey)
  File "/usr/lib/python2.7/multiprocessing/connection.py", line 169, in Client
b
    c = SocketClient(address)
  File "/usr/lib/python2.7/multiprocessing/connection.py", line 304, in SocketClient
    s.connect(address)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 2] No such file or directory
Process Process-3:
Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "/home/bluebird/Desktop/persiantext.py", line 27, in b
    if i in main_path:
  File "<string>", line 2, in __contains__
  File "/usr/lib/python2.7/multiprocessing/managers.py", line 755, in _callmethod
    self._connect()
  File "/usr/lib/python2.7/multiprocessing/managers.py", line 742, in _connect
    conn = self._Client(self._token.address, authkey=self._authkey)
  File "/usr/lib/python2.7/multiprocessing/connection.py", line 169, in Client
    c = SocketClient(address)
  File "/usr/lib/python2.7/multiprocessing/connection.py", line 304, in SocketClient
    s.connect(address)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 2] No such file or directory

请注意,我不知道在其中一个进程找到重复元素后如何终止这两个进程!!

1 个答案:

答案 0 :(得分:1)

您的代码中存在各种其他问题,但由于我已经在其他问题上解释了这些问题,因此我不会在此处进入。

新问题是您没有join您的子流程。在您的线程版本中,这不是一个问题,因为您的主线程意外地有一个&#34;永久阻止&#34;在结束之前。但是在这里,你还没有,所以当后台进程仍在运行时,主进程到达脚本的末尾。

当发生这种情况时,它并没有完全定义你的代码会做什么。 * 但基本上,你正在销毁管理器对象,这会关闭管理器服务器。后台进程仍在使用它,因此他们在下次尝试访问托管对象时会引发异常。

解决方案是将p1.join()p2.join()添加到脚本的末尾。

但这真的只会让你回到与线程代码相同的情况(除了最后不会永远阻塞)。您仍然拥有完全序列化的代码,并且竞争条件很严重,等等。

如果你很好奇为什么会这样:

在脚本结束时,所有模块的全局变量都超出范围。 ** 由于这些变量是管理器和过程对象的唯一引用,对象被垃圾收集,并且它们的析构函数被调用。

对于管理器对象,析构函数会关闭服务器。

对于进程对象,我并不完全确定,但我认为析构函数 nothing (而不是加入它和/或中断它)。相反,它有一个atexit函数,它在所有析构函数之后运行,它们连接任何仍在运行的进程。 ***

所以,首先经理离开,然后主要过程开始等待孩子们完成;下次每次尝试访问托管对象时,它都会失败并退出。一旦所有人都这样做,主要过程就会等待并退出。

* 3.2中的multiprocessing更改和3.4中的关闭更改使事情变得更加清晰,所以如果我们不讨论2.7,那么#34;这里&# 39;经常发生的事情,但并非总是如此。和&#34;这是在一个特定平台上的一个特定实现中发生的事情&#34;。

**这实际上并不是由2.7保证,并且垃圾收集所有模块&#39;全局变量并不总是发生。但是在这个特别简单的情况下,我非常确定它始终以这种方式工作,至少在CPython中,尽管我不想尝试解释原因。

***这肯定是它如何与线程一起工作,至少在Unix上的CPython 2.7上......再次,这根本没有记录在2.x中,所以你只能告诉它通过阅读源代码或试验对您来说重要的平台/实现/版本......我不想通过源跟踪这个问题,除非有可能找到令人费解或有趣的东西。