python 多进程报错:Can‘t pickle<function ISC>

本文介绍了一种在Python中使用多进程时遇到的问题及解决方案。作者最初使用标准的multiprocessing库时遇到了pickle无法序列化某些对象的情况,通过将multiprocessing替换成multiprocessing_on_dill库成功解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

各位大佬好,我在使用python多进程的时候遇到了一个问题

def multi_process():
#    with ProcessPoolExecutor() as pool:
#    pool = mp.Pool(mp.cpu_count())
    with mp.Pool() as pool:
        pool.starmap(ISC, [(l, t) for l in range(2 * brCount) for t in range(Time)])

if __name__ == "__main__":
    for_start = time.time()
    multi_process()
    for_end = time.time()

函数ISC定义为:

def ISC(l, t):
    global ISCR_C
    ISCR_C[:, 0] = ISCR_A[l, :]
    ISCR_C[:, 1] = ISCR_Pmax
    ISCR_C = ISCR_C[np.lexsort(-ISCR_C[:, ::-1].T)]
    if l <= brCount - 1:
        for k in range(GenCount - 1):
            if ISCR1(k, t) * ISCR2(k, t) * ISCR3(l, k, t) == 1:
                opt.remove_constraint(model.branch_Cap1[t, l])
                break
    else:
        for k in range(GenCount - 1):
            if ISCR1(k, t) * ISCR2(k, t) * ISCR3(l, k, t) == 1:
                opt.remove_constraint(model.branch_Cap2[t,l - brCount])
                break

程序运行会报错:

 第一次用多进程,除了问题也不知咋回事,有没有大佬能救救孩子


2021.12.21更新

问题好像解决了,python多进程使用的multiprocessing包默认使用pickle,但是pickle无法处理lambda、闭包之类的东西,把multiprocessing包换成multiprocessing_on_dill问题就解决了,更新后的程序大概是这样的:

# 调用multiprocessing_on_dill包
from multiprocessing_on_dill.dummy import Pool

# %% 主程序部分
def multi_process():
    with Pool() as pool:
        pool.starmap(ISC, [(l, t) for l in range(2 * brCount) for t in range(Time)])

if __name__ == "__main__":
    for_start = time.time()
    multi_process()
    for_end = time.time()
    for_caltime = (for_caltime + for_end - for_start) / (testtimes + 1)

在使用 `pickle` 序列化自定义类(如 `SwinTransformer`)时遇到的 `PicklingError: Can't pickle ... not the same object as itself` 错误,通常与 Python 的模块导入方式或类定义的位置有关。 该错误表明 `pickle` 在尝试序列化对象时发现其类定义不一致。具体来说,`SwinTransformer` 类可能在不同的模块上下文中被导入或重新定义,导致 `pickle` 无法正确识别类的来源路径。这种问题常见于以下几种情况: - **类定义位于非标准模块中**:例如,在脚本顶层直接定义类而不是将其放入明确的包结构中。 - **动态导入或相对导入**:尤其是在复杂项目结构中,如 YOLO 系列模型中常见的嵌套模块设计。 - **类名重复但实际引用不同**:多个模块中存在同名类,而 `pickle` 无法判断它们是否为同一类。 ### 解决方案 1. **确保类定义可被正确导入** 将 `SwinTransformer` 类定义放在一个独立的、可通过标准模块导入路径访问的文件中,并通过绝对导入引用它。例如: ```python from models.backbone import SwinTransformer ``` 而不是使用相对导入或直接在训练脚本中定义此类。 2. **使用 `dill` 替代 `pickle`** `dill` 是 `pickle` 的扩展版本,可以序列化更复杂的对象类型,包括某些闭包和嵌套函数等。 ```python import dill as pickle ``` 3. **避免动态创建类或修改类属性** 如果 `SwinTransformer` 类在运行时被动态修改或重新赋值,可能导致 `pickle` 无法追踪其原始定义。确保类定义在导入后保持不变。 4. **注册自定义类的别名(使用 `copyreg` 模块)** 可以通过 `copyreg.pickle()` 显式注册类的序列化方法,帮助 `pickle` 正确解析类对象。 5. **检查多重继承或混合模块中的类冲突** 如果 `SwinTransformer` 是从其他模块组合或混入的类构建而来,确保所有父类都能被正确导入且没有命名冲突。 6. **使用 `__module__` 属性修正类所属模块** 如果类在运行时被移动或复制,可以通过显式设置 `__module__` 属性来告诉 `pickle` 它属于哪个模块: ```python class SwinTransformer: ... SwinTransformer.__module__ = 'models.backbone' ``` ### 示例代码:使用 `dill` 替代 `pickle` ```python import dill as pickle # 假设 SwinTransformer 已正确定义并导入 model = SwinTransformer(...) with open('model.pkl', 'wb') as f: pickle.dump(model, f) ``` ### 示例代码:注册自定义类的序列化方法 ```python import copyreg import types def _reduce_method(m): return getattr, (m.__self__, m.__name__) # 注册对绑定方法的序列化支持 copyreg.pickle(types.MethodType, _reduce_method) # 再次尝试序列化包含方法的对象 with open('model.pkl', 'wb') as f: pickle.dump(model, f) ``` ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值