python pickle load序列化,从BytesIO中(文件流、stream)连续连续获取值(getvalue())

之前项目中接触过pickle的序列化和BytesIO的文件流。结果今天碰到问题了, 文件pickle.dump到BytesIO中后,不能反向取出来。。。查了半天感觉好多资料介绍的太简单了。。。没有几篇是讲BytesIO利用pickle连续写入在全部读取出来的操作。

贴几篇有帮助的:

https://stackoverflow.com/questions/30199393/how-can-pickled-byte-data-be-unpickled

https://stackoverflow.com/questions/53485708/how-the-write-read-and-getvalue-methods-of-python-io-bytesio-work

这篇:https://www.twle.cn/t/452

是比较详细的,讲到了BytesIO和pickle组合的连续读写的文件流操作,正是我需要的。

 

我对pickle序列化的理解就是讲Python的任意对象,比如类,实力,列表,字典等等转换成二进制,感觉json很像,区别是一个二进制一个字符串?

BytesIO之前只简单看过,今天看了下他的功能就是把文件写入内存?像是一个文件流。

这都不是关键。键是pickle和BytesIO结合起来的读写,以及文件指针位置。。。

先说重点 ,我需要解决的问题。

import pickle,io

io_buffer=io.BytesIO()

pickle.dump('a',io_buffer)
pickle.dump('b',io_buffer)
print(pickle.load(io_buffer))
print(pickle.load(io_buffer))

开始代码这么写,期望能输出a,b,结果却直接报错:
EOFError: Ran out of input

原因就是io_buffer的指针位置在最后,自然读取不到文件了,所以需要重置指针位置到开始处,代码改成这要就好了

pickle.dump('a',io_buffer)
pickle.dump('b',io_buffer)
#重置指针位置
io_buffer.seek(0)
print(pickle.load(io_buffer))
print(pickle.load(io_buffer))

正常输出:
a
b

或者重新生成一个BytesIO对象

pickle.dump('a',io_buffer)
pickle.dump('b',io_buffer)

#重新生成BytesIO对象
new_io_buffer=io.BytesIO(io_buffer.getvalue())
# io_buffer.seek(0)
print(pickle.load(new_io_buffer))
print(pickle.load(new_io_buffer))

 

 

不过还有一点不明白的是,getvalue,下面代码getvalue(),期望是获取全部结果abc,但是对getvalue得到的结果res进行pickle.loads反序列化后,只能得到a,而直接对res进行decode确实是能得到全部的之abc,长度33也证明是3个字符的长度。

pickle.dump('a',io_buffer)
pickle.dump('b',io_buffer)
pickle.dump('c',io_buffer)

res=io_buffer.getvalue()
print(res.decode(errors='ignore'))
print(len(res),pickle.loads(res)

输出结果:

X   aq .X   bq .X   cq .
33 a

如果不用pickle.load写入,用write写入,getvalue就没问题,就会得到全部结果:abc,求高人指点。。。。

io_buffer.write(b'a')
io_buffer.write(b'b')
io_buffer.write(b'c')
res=io_buffer.getvalue()
print(len(res),res)

输出结果:

3 b'abc'
 

 

 

最后说一下文件指针,主要是seek的两个参数:offset,whence,参考菜鸟教程的说明:

  • offset -- 开始的偏移量,也就是代表需要移动偏移的字节数

  • whence:可选,默认值为 0。给offset参数一个定义,表示要从哪个位置开始偏移;0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。

io_buffer.write(b'a')
io_buffer.write(b'b')
io_buffer.seek(0)
io_buffer.write(b'c')
print(io_buffer.getvalue())

如果没有这句代码:io_buffer.seek(0),输出结果结果应该是abc,重置了指针位置到开始位置后,c覆盖了a,所以输出结果:

b'cb'

io_buffer.write(b'a')
io_buffer.write(b'b')

io_buffer.seek(-1,2)
io_buffer.write(b'c')
# print(io_buffer.read())
print(io_buffer.getvalue())

io_buffer.seek(-1,2)这句话2代表最后位置,-1表示向前移动一个位置,所以b就会被c覆盖输出结果:
b'ac'

io_buffer.write(b'a')
io_buffer.write(b'b')
io_buffer.seek(2,2)
io_buffer.write(b'c')
# print(io_buffer.read())
#结果不解码
print(io_buffer.getvalue())
#对结果解码
print(io_buffer.getvalue().decode())

io_buffer.seek(2,2)最后位置再向后移动两个位置,应该是多了两个空格,输出结果:


b'ab\x00\x00c'

ab  c

测试到此为止!

你可能感兴趣的:(python pickle load序列化,从BytesIO中(文件流、stream)连续连续获取值(getvalue()))