TypeError:init()缺少1个必需的位置参数:'message'使用Multiprocessing

pyt*_*ist 9 python multithreading multiprocessing python-3.x python-3.4

我正在使用多处理池运行一段代码.代码在数据集上工作,在另一个上失败.显然问题是数据驱动 - 我说我不清楚从哪里开始故障排除,因为我收到的错误如下.任何关于起点的提示都将是最有帮助的.这两组数据都使用相同的代码编写 - 所以我不认为会有差异 - 但我在这里.

另请参阅Robert的评论 - 我们在os和python版本3.6(我有3.4,他有3.6)和完全不同的数据集上有所区别.然而,错误与python代码中的行完全相同.

我的怀疑:

  1. 每个核心都有一个内存限制正在执行.
  2. 在一段时间之后,该过程逐字地收集 - 发现过程没有结束并放弃.

    线程Thread-9中的异常:

    Traceback(最近一次调用最后一次):

    文件"C:\ Program Files\Python\WinPython-64bit-3.4.4.4Qt5\python-3.4.4.amd64\lib\threading.py",第911行,在_bootstrap_inner self.run()中

    文件"C:\ Program Files\Python\WinPython-64bit-3.4.4.4Qt5\python-3.4.4.amd64\lib\threading.py",第859行,运行self._target(*self._args,**self._kwargs)

    文件"C:\ Program Files\Python\WinPython-64bit-3.4.4.4Qt5\python-3.4.4.amd64\lib\multiprocessing\pool.py",第429行,在_handle_results task = get()中

    文件"C:\ Program Files\Python\WinPython-64bit-3.4.4.4Qt5\python-3.4.4.amd64\lib\multiprocessing\connection.py",第251行,在recv中返回ForkingPickler.loads(buf.getbuffer( ))

    TypeError:init()缺少1个必需的位置参数:'message'

Rob*_*ley 6

我认为问题是langdetect在这里悄悄声明了一个隐藏的全球探测器工厂https://github.com/Mimino666/langdetect/blob/master/langdetect/detector_factory.py#L120:

def init_factory():
    global _factory
    if _factory is None:
        _factory = DetectorFactory()
        _factory.load_profile(PROFILES_DIRECTORY)

def detect(text):
    init_factory()
    detector = _factory.create()
    detector.append(text)
    return detector.detect()


def detect_langs(text):
    init_factory()
    detector = _factory.create()
    detector.append(text)
    return detector.get_probabilities()
Run Code Online (Sandbox Code Playgroud)

根据我的经验,这种事情可能导致多处理中的问题,因为多方处理试图在进程内共享内存中的资源并管理工作者和主进程中的命名空间的方式,尽管在这种情况下确切的机制是黑色的盒子给我.我通过向init_factory池初始化函数添加函数调用来修复它:

from langdetect.detector_factory import init_factory
def worker_init_corpus(stops_in):
    global sess
    global stops
    sess = requests.Session()
    sess.mount("http://", HTTPAdapter(max_retries=10))
    stops = stops_in
    signal.signal(signal.SIGINT, signal.SIG_IGN)
    init_factory()
Run Code Online (Sandbox Code Playgroud)

仅供参考:"sess"逻辑是为每个工作者提供一个用于请求的http连接池,以便在将该模块与多处理池一起使用时遇到类似问题.如果你不这样做,工作人员会通过父进程备份所有的http通信,因为默认情况下隐藏的全局http连接池就是这样,然后一切都非常缓慢.这是我遇到的一个问题,这让我怀疑这里有类似的原因.

此外,为了进一步减少潜在的混淆:stops用于提供我用于映射函数的禁用词列表.并且signal调用是在用用户中断(ctrl-c)命中时强制池很好地退出.否则他们经常会成为孤儿,并在父进程死后继续忙碌.

然后我的池初始化如下:

self.pool = mp.Pool(mp.cpu_count()-2, worker_init_corpus, (self.stops,))
Run Code Online (Sandbox Code Playgroud)

我还把我的调用包裹detect在try/catch LangDetectExeception块中:

try:
    posting_out["lang"] = detect(posting_out["job_description"])
except LangDetectException:
    posting_out["lang"] = "none"
Run Code Online (Sandbox Code Playgroud)

但这并不能解决它自己.非常有信心初始化是修复.