问题

有的类是不支持在多进程间传递的,如果非要这么做,可能会引发奇怪的现象。比如下面这段代码:

from concurrent.futures import ProcessPoolExecutor, as_completed

from pymysql import connect

class MySqlDatabase(object):

    def __init__(self, host='127.0.0.1', port=3306, user='root', pwd='', db=None):
self.host = host
self.port = port
self.user = user
self.pwd = pwd
self.db = db
self.conn = self.connect() def connect(self):
return connect(host=self.host, port=self.port, user=self.user, password=self.pwd, database=self.db) def runquery(self, q):
with self.conn.cursor() as cur:
cur.execute(q)
return cur def run_in_pool(db, sql):
print(db.runquery(sql)) def run():
quires = ['show tables',
'select * from user']
db = MySqlDatabase(pwd='1234', db='mysql')
with ProcessPoolExecutor() as e:
fs = [e.submit(run_in_pool, db, q) for q in quires]
for f in as_completed(fs):
print(f.result()) if __name__ == '__main__':
run()

这段代码运行后会卡在 for f in as_completed(fs): 这一行,有的平台会抛出异常 TypeError: cannot serialize '_io.BufferedReader' object,有的则什么都不显示,这是因为 pymysql 提供的 Connection 对象是不可序列化的,因此多为多进程间的参数传递会产生异常。

那么,如果让这里的 MySqlDatabase 实例支持在多进程间传递呢?

解决方案

Python 提供了 __getstate____setstate__ 方法以支持类进一步控制其实例的封存过程,这会使的实例可以被 pickle 序列化,正确实现这两个方法,实例在多进程间就可以正常传递了。

以上面的问题为例,更改 MySqlDatabase 实现如下:

class MySqlDatabase(object):

	...

    def __getstate__(self):
state = self.__dict__.copy()
# 移除不可序列化的属性
state.pop('conn')
return state def __setstate__(self, state):
self.__dict__.update(state)
# 重新绑定移除的属性
self.conn = self.connect()

更新后,再次运行,就会得到预期的结果了。

扩展

  • 如果类定义了 __getstate__(),它就会被调用,其返回的对象是被当做实例内容来封存的,否则封存的是实例的 __dict__
  • 当解封时,如果类定义了 __setstate__(),就会在已解封状态下调用它。此时不要求实例的 state 对象必须是 dict。没有定义此方法的话,先前封存的 state 对象必须是 dict,且该 dict 内容会在解封时赋给新实例的 __dict__
  • 该方法同样适用于 copy.copy 以提供新的拷贝对象

控制 Python 类的序列化过程的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议——建议56:使用继承ISerializable接口更灵活地控制序列化过程

    建议56:使用继承ISerializable接口更灵活地控制序列化过程 接口ISerializable的意义在于,如果特性Serializable,以及与其像配套的OnDeserializedAttr ...

  2. 【转】编写高质量代码改善C#程序的157个建议——建议56:使用继承ISerializable接口更灵活地控制序列化过程

    建议56:使用继承ISerializable接口更灵活地控制序列化过程 接口ISerializable的意义在于,如果特性Serializable,以及与其像配套的OnDeserializedAttr ...

  3. 【python】-- 类的实例化过程、特征、共有属性和私有属性

    实例化过程 1.类的定义和语法 class dog(object): #用class定义类 "dog class" #对类的说明 def __init__(self,name): ...

  4. python原类、类的创建过程与方法

    今天为大家介绍一下python中与class 相关的知识-- 获取对象的类名 python是一门面向对象的语言,对于一切接对象的python来说,咱们有必要深入的学习与了解一些知识 首先大家都知道,要 ...

  5. 细说python类3——类的创建过程

    细说python类3——类的创建过程 https://blog.csdn.net/u010576100/article/details/50595143 2016年01月27日 18:37:24 u0 ...

  6. Python 之 Json序列化嵌套类

    想要用python自已手动序列化嵌套类,就要明白两个问题: 1.Json是什么? 2.Json支持什么类型? 答案显而易见 Json就是嵌套对象 Json在python中支持列表,字典(当然也支持in ...

  7. 第8.8节 Python使用__new__方法和构造方法__init__完成类实例化的过程详解

    第8.8节 Python使用__new__方法和构造方法__init__完成类实例化的过程详解 前面章节介绍了Python类中的__new__方法和构造方法__init__,并通过实例分析了二者之间关 ...

  8. python类:magic魔术方法

    http://blog.csdn.net/pipisorry/article/details/50708812 魔术方法是面向对象Python语言中的一切.它们是你可以自定义并添加"魔法&q ...

  9. (转)python类:magic魔术方法

    原文:https://blog.csdn.net/pipisorry/article/details/50708812 版权声明:本文为博主皮皮http://blog.csdn.net/pipisor ...

随机推荐

  1. Spark面试题(七)——Spark程序开发调优

    Spark系列面试题 Spark面试题(一) Spark面试题(二) Spark面试题(三) Spark面试题(四) Spark面试题(五)--数据倾斜调优 Spark面试题(六)--Spark资源调 ...

  2. KNN算法实现对iris数据集的预测

    KNN算法的实现 import pandas as pd from math import dist k = int(input("请输入k值:")) dataTest = pd. ...

  3. 一类利用队列优化的DP

    I.导入: 这是一个\(O(n^2)\)的状态和转移方程: \[f(i,j)=\left\{ \begin{aligned} f(i-1,j-1)+k \ (1\leq j)\\ \max_{k \i ...

  4. doxygen相关命令

    主要配置修改 整个程序配置分几个部分 Project related configuration options 项目相关,包括: 项目名 输出目录 输出语言 是否显示继承属性 是否对C.Java.F ...

  5. composer设置阿里云镜像源

    composer设置阿里云镜像源 1. 首先把默认的源给禁用掉 composer config -g secure-http false 2. 再修改镜像源 这里我使用阿里的源 composer co ...

  6. MongoDB的搭建、参数

    Mongodb官网:https://www.mongodb.com/ mkdir -r  /data/db touch  /data/log tar -zxvf mongodb-linux-x86_6 ...

  7. Spark3学习入门【基于Java】

    Spark 是离线数据处理的一种大数据技术,和Flick相比数据处理要延后,因为Flick是实时数据处理,而Spark需要先读取数据到内存. Spark的库是基于Scala写的,虽然Scala也是运行 ...

  8. UE4之Slate: SImage

    概述 距离上次记录<UE4之Slate:纯C++工程配置>后已经好长时间了: 这个随笔来记录并分享一下SImage控件的使用,以在屏幕上显示一张图片: 目标 通过SImage控件的展示,学 ...

  9. 使用flock命令查看nas存储是否支持文件锁

    上锁 文件锁有两种 shared lock 共享锁 exclusive lock 排他锁 当文件被上了共享锁之后,其他进程可以继续为此文件加共享锁,但此文件不能被加排他锁,此文件会有一个共享锁计数,加 ...

  10. python写的多项式符号乘法

    D:\>poly.py(x - 1) * (x^2 + x + 1) = x^3 - 1 1 import ply.lex as lex # pip install ply 2 import p ...