控制 Python 类的序列化过程
2024-09-27 03:44:21
问题
有的类是不支持在多进程间传递的,如果非要这么做,可能会引发奇怪的现象。比如下面这段代码:
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
以提供新的拷贝对象
最新文章
- 3Sum algorithm - 非常容易理解的实现 (java)
- python word
- JavaScript中reduce()方法
- 【Java每日一题】20161017
- jsoncpp封装和解析字符串、数字、布尔值和数组
- (DFS)zoj1008-Gnome Tetravex
- Filezilla Server 配置大全
- Item2 + zsh
- Hadoop概念学习系列之hadoop、spark常备查询网址(二十九)
- ubuntu 14.04 安装preforce
- Organic Solar Cells - Generations of Solar Cells
- Scala入门系列(八):面向对象之trait
- 以独立的语句将new对象置入智能指针
- Git入门基础详情教程
- 使用Ansible实现数据中心自动化运维管理
- ida+gdb调试任意平台
- js多物体运动之淡入淡出效果
- Ionic3--数据存储
- slack机器人运维
- Linux安装centos7