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

时间:2017-04-07 01:25:40

标签: python multithreading python-3.x multiprocessing python-3.4

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

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

我的怀疑:

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

    Thread-9中的异常:

    追踪(最近一次呼叫最后一次):

    文件“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'

3 个答案:

答案 0 :(得分:5)

我认为问题是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()

根据我的经验,这种事情可能导致多处理中的问题,因为多方处理试图在进程内部共享资源并管理工作程序和主进程中的命名空间的方式,尽管在这种情况下的确切机制对我来说是一个黑盒子。我通过向我的池初始化函数添加对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()

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

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

然后我的游泳池被初始化为:

self.pool = mp.Pool(mp.cpu_count()-2, worker_init_corpus, (self.stops,))

我还在try {catch detect块中将我的电话打包到LangDetectExeception

try:
    posting_out["lang"] = detect(posting_out["job_description"])
except LangDetectException:
    posting_out["lang"] = "none"

但这并没有解决它自己。非常确信初始化是修复。

答案 1 :(得分:1)

感谢罗伯特 - 专注于朗检测产生了一个事实,即我的一个文本条目可能是空的

LangDetectException:文本中没有任何功能

菜鸟错误 - 可能是由于编码错误 - 在过滤掉这些错误后重新运行 - 会让你(罗伯特)发布。

答案 2 :(得分:1)

我在代码中的某处抛出了一个自定义异常,并且它在我的大多数进程中(在池中)被抛出。我大约 90% 的进程进入睡眠状态,因为它们发生了这个异常。但是,我没有得到正常的回溯,而是得到了这个神秘的错误。不过,我的是 Linux。

为了调试这个,我删除了池并按顺序运行代码。