问题

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

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. [hdu7013]String Mod

    枚举$a$​​​和$b$​​​​​出现的次数,问题即求$$A_{i,j}=\sum_{p=0}^{L}\sum_{q=0}^{L-p}[n\mid (p-i)][n\mid (q-j)]{L\choo ...

  2. [loj2978]杜老师

    假设所有素数从小到大依次为$p_{1},p_{2},...,p_{k}$,我们将$x$转换为一个$k$位的二进制数,其中从低到高第$i$位为1当且仅当其$p_{i}$的幂次为奇数 不难发现以下两个性质 ...

  3. [hdu6761]Minimun Index

    $lyndon\ word$(以下简写为Lw):对于一个字符串s,其为Lw当且仅当其的最小后缀为自身 性质:若$u<v$为LW,那么$uv$也为Lw(反证法即可证) $lyndon$分解:将一个 ...

  4. 多线程02.继承Thread类

    package chapter2; /** * 1.使用static虽然完成了当前的功能. * 但是static的生命周期比较长,需要在所有线程执行完成后才会结束. * 还有号没有按照顺序进行打印 * ...

  5. 对于cmd命令的一些常用用法

    cmd命令是当今比较常见的主机命令,对于一些文件的执行和后台数据的控制有着比较有效的规范. 现在就讲几个比较常见的命令. IP查询 按住window+r 进入控制台,在输入cmd命令.在弹出的 cmd ...

  6. SpringCloud升级之路2020.0.x版-43.为何 SpringCloudGateway 中会有链路信息丢失

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在开始编写我们自己的日志 Filter 之前,还有一个问题我想在这里和大家分享,即在 Sp ...

  7. Atcoder Grand Contest 022 E - Median Replace(dp)

    Atcoder 题面传送门 & 洛谷题面传送门 首先考虑对于固定的 01 串怎样计算它是否可以通过将三个连续的 \(0\) 或 \(1\) 替换为其中位数得到.我们考虑单调栈,新建一个栈,栈底 ...

  8. 区分wsgi、uWSGI、uwsgi、php-fpm、CGI、FastCGI

    在学习Python web开发时候,可能会遇到诸如uwsgi,wsgi等名词,下面通过梳理总结探究它们之间的关系. CGI CGI,(Common Gateway Interface)通用网关接口,是 ...

  9. Python基础之赋值与注释

    目录 1. 花式赋值 1.1 链式赋值 1.2 交叉赋值 1.3 交叉赋值(解压缩) 2. 注释 2.1 单行注释 2.2 多行注释 1. 花式赋值 1.1 链式赋值 a = 10 b = 10 c ...

  10. 禁止点击、禁止button触发【c#】

    bts.Attributes["onclick"] = "return false; ";