【问题标题】:TypeError while using Pool from multiprocessing (python 3.7)使用来自多处理的池时出现 TypeError(python 3.7)
【发布时间】:2021-01-06 20:36:52
【问题描述】:

我试图总结一个目录中所有文件的大小,包括递归子目录。如果我只调用一次,相关函数 (self._count) 就可以正常工作。但是对于大量文件,我想使用multiprocessing 来使程序更快。以下是代码的相关部分。

self._sum_dict 将给定字典的相同键的值相加。
self._get_file_type 返回应放置文件的类别(stats 的键)。
self._categories 保存一个列表所有可能的类别。
number_of_threats 指定应使用的工作人员数量。
path 保存第一句中所指目录的路径。

import os
from multiprocessing import Pool

def _count(self, path):
    stats = dict.fromkeys(self._categories, 0)
    try:
        dir_list = os.listdir(path)
    except:
        # I do some warning here, but removed it for SSCCE
        return stats

    for element in dir_list:
        new_path = os.path.join(path, element)

        if os.path.isdir(new_path):
            add_stats = self._count(new_path)
            stats = self._sum_dicts([stats, add_stats])
        else:
            file_type = self._get_file_type(element)
            try:
                size = os.path.getsize(new_path)
            except Exception as e:
                # I do some warning here, but removed it for SSCCE
                continue

            stats[file_type] += size

    return stats

files = []
dirs = []
for e in dir_list:
    new_name = os.path.join(path, e)
    if os.path.isdir(new_name):
        dirs.append(new_name)
    else:
        files.append(new_name)

with Pool(processes=number_of_threats) as pool:
    res = pool.map(self._count, dirs)

self._stats = self._sum_dicts(res)

我知道,这段代码不会考虑path 中的文件,但这是我可以轻松添加的内容。执行代码时出现以下异常。

Exception has occurred: TypeError
cannot serialize '_io.TextIOWrapper' object
...
line ... in ...
res = pool.map(self._count, dirs)

我发现,在共享进程之间的资源时可能会发生此异常,据我所知,我只对stats = dict.fromkeys(self._categories, 0) 执行此操作。但是用硬编码值替换这一行并不能解决问题。即使在这一行设置断点也无济于事,因为它没有到达。

有人知道这个问题的原因是什么以及我该如何解决这个问题?

【问题讨论】:

    标签: python python-3.x multiprocessing python-3.7


    【解决方案1】:

    问题是你试图传递“自我”。如果 self 有一个 Stream 对象,它就不能被序列化。

    尝试将多处理代码移出类。

    Python 多处理会启动一个新的解释器,如果您尝试访问无法腌制(或序列化)的共享代码,它会失败。通常它不会在您认为它崩溃的地方崩溃……但是在尝试接收对象时。 我将使用线程的代码转换为多处理,即使我没有发送或使用这些对象,我也遇到了很多奇怪的错误,但我使用了它们的父级(self)

    【讨论】:

    • 感谢您的回答!我尝试将_count 函数的代码以及在其中调用的所有函数放在类之外,有效地使它们成为正常函数。但是现在我有一个问题,我不知道如何为这些函数提供附加参数,例如所有可能类别的列表。您知道如何实现吗?
    • 这是另一个问题 althoghether.. 你必须使用 multiprocessing amd Manager.queue/list 或其他的 Manager ......我没有深入研究......但是 Lock and Queue from那里工作。当您将作业添加到池中时,您只需将其作为参数传输。
    • 如果你想修改这些元素,如果不只是给它们作为参数,python 会复制
    猜你喜欢
    • 2016-12-07
    • 1970-01-01
    • 2021-07-24
    • 2020-08-14
    • 2016-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多