gpt4 book ai didi

python - 程序与 map() 一起工作,但通过 pool.map() 引发 TypeError

转载 作者:太空宇宙 更新时间:2023-11-03 11:28:49 26 4
gpt4 key购买 nike

我确实有一个程序,虽然已经有一段时间没有使用了,但是已经使用过并且可以运行了。它使用多重处理,因为必须多次为不同的数据完成相同的任务。

我现在触摸程序以添加新参数,对其进行测试并注意到它出现了错误。较早的(版本控制的)版本也出现了同样的错误。完整的错误如下所示:

Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib64/python2.7/threading.py", line 811, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.7/threading.py", line 764, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib64/python2.7/multiprocessing/pool.py", line 342, in _handle_tasks
put(task)
TypeError: 'NoneType' object is not callable

就是这样。老实说,这对我来说没什么意义。在尝试对此进行调试时,我想到了尝试使用普通 map() 而不是合并版本 pool.map 的想法。然后脚本运行正常。

我无法想出一个重现错误的最小示例,但我可以想出一个示例,其中一切正常,正如预期的那样:

import random
import time
from multiprocessing import Pool


def do_work(x, y, z):
time.sleep(random.random() * 2)
print x + y + z

def do_one(arguments):
print "doing one"
do_work(*arguments)

def do_many(x, y, zs):
map(do_one, [(x, y, z) for z in zs])

def do_many_pooled(x, y, zs):
pool = Pool(2)
pool.map(do_one, [(x, y, z) for z in zs])
pool.close()
pool.join()

def main():
x = 1
y = 2
zs = range(10)
print "doing many"
do_many(x, y, zs)
print "doing many pooled"
do_many_pooled(x, y, zs)


if __name__ == '__main__':
main()

真实程序执行大量数据库请求、使用 numpy 进行计算并将结果存储回数据库。在实际程序中,当使用池化版本时,程序在打印“doing one”之前出现错误并退出,但使用非池化版本运行良好。

有谁知道如何正确读取 Traceback 和/或可以告诉我什么可能导致此异常?

最佳答案

我会说它看起来像 put 从这部分被破坏了一个设置为 None回溯:

File "/usr/lib64/python2.7/multiprocessing/pool.py", line 342, in _handle_tasks
put(task)
TypeError: 'NoneType' object is not callable

查看Python源码,Pool.__init__()正在设置_task_handler它将调用 _handle_tasks 并提供参数说电话:

self._task_handler = threading.Thread(
target=Pool._handle_tasks,
args=(self._taskqueue, self._quick_put, self._outqueue, self._pool)
)

如果您查看 _handle_tasks,您会发现 self._quick_put 是结束的地方up 是 put 变量:

@staticmethod
def _handle_tasks(taskqueue, put, outqueue, pool, cache):
thread = threading.current_thread()

for taskseq, set_length in iter(taskqueue.get, None):
i = -1
for i, task in enumerate(taskseq):
if thread._state:
debug('task handler found thread._state != RUN')
break
try:
put(task)
except Exception as e:
job, ind = task[:2]
try:
cache[job]._set(ind, (False, e))
except KeyError:
pass
else:
if set_length:
debug('doing set_length()')
set_length(i+1)
continue
break
else:
debug('task handler got sentinel')

此外,您可以看到所有异常都在这里被捕获并隐藏起来以便稍后报告。但是,如果您回到 Python 2.7.6,您会看到:

@staticmethod
def _handle_tasks(taskqueue, put, outqueue, pool):
thread = threading.current_thread()

for taskseq, set_length in iter(taskqueue.get, None):
i = -1
for i, task in enumerate(taskseq):
if thread._state:
debug('task handler found thread._state != RUN')
break
try:
put(task)
except IOError:
debug('could not put task on queue')
break
else:
if set_length:
debug('doing set_length()')
set_length(i+1)
continue
break
else:
debug('task handler got sentinel')

请注意,TypeError 可能会转义。原来这是固定的由于错误#19425 .奇怪的是,它是声称这不是 Python 2.7 中的问题,但变更集仍然是向后移植。

无论如何,在任何一种情况下,put() 应该是一个已知值,并且没有似乎可以通过任何方式在此代码中设置 put。所以,对我来说,它闻起来像 bug 在 Python 中。您可以在更新版本的下运行相同的代码 python ?

一些其他有用的信息

Google 的快速搜索也会返回一些有趣的结果:

  • Python 错误 #9755 - 相似但不同堆栈跟踪。

  • Python 错误 #15881 - 与上述类似,但堆栈跟踪也略有不同。

两者都是清理影响模块状态并导致事情发生的问题失败并出现“'NoneType' 对象不可调用”异常。

其他一些相关的错误也存在于 Python 中。有一次你可以使用守护线程并退出时遇到类似的异常你的应用程序的主线程。我忘记了哪个版本是固定的。我只是想表明这种问题并非闻所未闻,并且是 python 。

关于python - 程序与 map() 一起工作,但通过 pool.map() 引发 TypeError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27704598/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com