可序列化类型和多进程 PicklingError
遇到一个报错:
PicklingError: Can't pickle <type'instancemethod'>: attribute lookup __builtin__.instancemethod failed
当时的情况是想写一个多进程的解析代码,爬虫爬到的内容给扔过来就不管了,差不多这个意思:
# !/usr/bin/env python
# -*- coding: utf-8 -*-
from concurrent.futures import ProcessPoolExecutor
class PageProcess(object):
    def __init__(self, worker):
        self.max_worker = worker
    def single_process(self, page):
        pass
    def multi_process(self, page_list):
        with ProcessPoolExecutor(max_workers=self.max_worker) as pp:
            result = pp.map(self.single_process, page_list)
这个错误是这么造成的:
- 在类中使用进程池;
- 进程池使用 Queue管理任务队列;
- Queue要求传递的内容必须都是可以被序列化的;
那么问题来了,哪些类型是可以被序列化的呢?
根据 官方文档,可序列化的类型包括:
| 类型 | 原文 | 
|---|---|
| 布尔型和空值 | None,True, andFalse | 
| 数字类型中的整数,浮点数和复数 | integers, floating point numbers, complex numbers | 
| 字符串类型和二进制类型 (字节流,字节数组) | strings, bytes, bytearrays | 
| 只包含可序列化对象的元组、集合、列表、字典 | tuples, lists, sets, and dictionaries containing only picklable objects1 | 
| 模块中最顶层声明的非匿名函数 | functions defined at the top level of a module (using def, not lambda) | 
| 模块中最顶层声明的内置函数 | built-in functions defined at the top level of a module | 
| 模块中最顶层声明的类 | classes that are defined at the top level of a module | 
| __getstate__的结果或__dict__是可序列化的这样的类的实例 | instances of such classes whose __dict__or the result of calling__getstate__()is picklable | 
破案了,上面代码中,我们的进程池要序列化的是类中的函数,就不符合最顶层定义的函数的要求。
所以最直接的解决办法也很简单,把要并行的函数抽外面去就行了:
# !/usr/bin/env python
# -*- coding: utf-8 -*-
from concurrent.futures import ProcessPoolExecutor
def single_process(page):
    pass
class PageProcess(object):
    def __init__(self, worker):
        self.max_worker = worker
    def multi_process(self, page_list):
        with ProcessPoolExecutor(max_workers=self.max_worker) as pp:
            result = pp.map(single_process, page_list)
- 
英文这种语序 / 标点我老是搞不懂,这个 containing only picklable objects到底是指 dictionaries 还是前面全部,就当是全部吧 ↩︎
