www.zhblog.net

python序列化对象

在python中大多情况使用 pickle 模块对数据、对象进行序列化。


使用 dump 序列化python对象进文件

>>> import pickle
>>> data = 'i love python'
>>> f = open(r'e:\path\data.p', 'wb')
>>> pickle.dump(data, f)
>>> f.close()


使用 dumps 序列化python对象为字节对象

>>> pickle.dumps(data)
b'\x80\x03X\r\x00\x00\x00i love pythonq\x00.'


使用 load 从文件中恢复python对象

>>> f = open(r'e:\path\data.p', 'rb')
>>> pickle.load(f)
'i love python'


使用 loads 从字节中恢复python对象

>>> b = pickle.dumps(data)
>>> b
b'\x80\x03X\r\x00\x00\x00i love pythonq\x00.'
>>> pickle.loads(b)
'i love python'


pickle 使用一种特定的自描述数据编码,序列化的每个对象数据都包含开始结束相关信息以及类型的相关信息

>>> import pickle
>>> f = open(r'e:\path\data.p', 'wb')
>>> pickle.dump([1, 2, 3, 4], f)
>>> pickle.dump('hello', f)
>>> pickle.dump({'apple', 'pear', 'banana'}, f)
>>> f.close()
>>> f = open(r'e:\path\data.p', 'rb')
>>> pickle.load(f)
[1, 2, 3, 4]
>>> pickle.load(f)
'hello'
>>> pickle.load(f)
{'banana', 'apple', 'pear'}
>>> pickle.load(f)
Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    pickle.load(f)
EOFError: Ran out of input


也可以使用 pickle 序列化类和方法,但此时序列化的仅仅是与之相关的一些名称而已

>>> class T:
	def __init__(self):
		self.name = 't'

		
>>> pickle.dumps(T)
b'\x80\x03c__main__\nT\nq\x00.'
>>> t = T()
>>> pickle.dumps(t)
b'\x80\x03c__main__\nT\nq\x00)\x81q\x01}q\x02X\x04\x00\x00\x00nameq\x03X\x01\x00\x00\x00tq\x04sb.'

>>> import math
>>> pickle.dumps(math.cos)
b'\x80\x03cmath\ncos\nq\x00.'


pickle.load() 不用用于不受信任的数据,load 会自动加载模块并生成实例,所以可以模拟出pickle数据,然后执行任意python命令。


python中文件、网络、线程、进程、堆栈是不能被序列化的。自定义的类可以使用 __getstate__()__setstate__() 加以控制。pickle序列化时会调用 __getstate__,pickle反序列化时会调用 __setstate__。

>>> import time
>>> import threading
>>> class Countdown:
	def __init__(self, n):
		self.n = n
		self.thr = threading.Thread(target=self.run)
		self.thr.daemon = True
		self.thr.start()
	def run(self):
		while self.n > 0:
			print('T-minus', self.n)
			self.n -= 1
			time.sleep(5)
	def __getstate__(self):
		return self.n
	def __setstate__(self, n):
		self.__init__(n)

		
>>> c = Countdown(20)
T-minus
>>>  20

>>> 
>>> T-minus 19
T-minus 18
T-minus 17
T-minus 16
f = open(r'e:\path\cstate.p', 'wb')
>>> T-minus 15
T-minus 14
T-minus 13
pickle.dump(c, f) # 序列化在12未出时
>>> T-minus 12
f.close()
>>> 
>>> T-minus 11
T-minus 10
T-minus 9
T-minus 8
>>> T-minus 7
>>> T-minus 6
T-minus 5
T-minus 4
T-minus 3
>>> T-minus 2
>>> T-minus 1
>>> 
>>> f = open(r'e:\path\cstate.p', 'rb')
>>> pickle.load(f) # load此时会调用 init(12) 
T-minus<__main__.Countdown object at 0x00000000031E9358> 
12
>>> 
T-minus 11
T-minus 10
T-minus 9
T-minus 8
T-minus 7
T-minus 6
T-minus 5
T-minus 4
T-minus 3
T-minus 2
T-minus 1


pickle 不宜最为长期存储和大数据存储。

展开阅读全文

评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 心情