Python3解析字节对象的字符串表示

5

有没有一种好的方法来加载一个被表示为字符串的字节对象,以便可以取消序列化?

基本示例

这是一个愚蠢的示例:

import pickle

mydict = { 'a': 1111, 'b': 2222 }
string_of_bytes_obj = str(pickle.dumps(mydict)) # Deliberate string representation for this quick example.

unpickled_dict = pickle.loads(string_of_bytes_obj) # ERROR!  Loads takes bytes-like object and not string.

解决方案尝试

一种解决方法当然是对字符串进行eval

unpickled_dict = pickle.loads(eval(string_of_bytes_obj))

但是,使用eval似乎不太妥当,特别是当字符串可能来自网络或文件时。

...

有更好的解决方案吗?

谢谢!


我认为最好不要将字节转换为字符串。有没有任何方法可以避免这种转换? - awesoon
1
@soon 我只是在处理别人的文件...最好改变他们的文件使用二进制数据...但现在,我无法避免字符串转换。 - jehad
1
顺便说一下,使用pickle处理网络数据不是一个好主意:http://www.zopatista.com/plone/2007/11/09/one-cookie-please/ - Farhan.K
你知道这个文件的编码是什么吗?如果知道,你只需要使用 str.encode 将字符串解除 pickle。如果不知道,你需要先猜测编码。 - Jacques Gaudin
@JacquesGaudin 不太确定我理解了。字符串的编码是什么?我知道文件是utf-8,但我认为这只是让我以已知编码获取字符串表示形式的一种方式,我仍然需要评估...或者你是指@Farhan.K提供的答案之类的东西吗? - jehad
是的,我指的是类似于@Farhan.K答案中提到的内容,但由于您从给定文件获取字符串,因此必须知道使用哪种编码来生成它。如果您知道它,就可以反转操作以获取字节对象并取消pickle。 - Jacques Gaudin
4个回答

7

出于安全考虑,您可以使用ast.literal_eval代替eval:

>>> import ast
>>> pickle.loads(ast.literal_eval(string_of_bytes_obj))
{'b': 2222, 'a': 1111}

谢谢。非常好的答案。更安全的评估,只需要一些额外的错误处理。 - jehad

4

您可以使用encoding="latin1"作为str方法的参数,然后使用bytes将其转换回来:

import pickle

mydict = { 'a': 1111, 'b': 2222 }
string_of_bytes_obj = str(pickle.dumps(mydict), encoding="latin1")

unpickled_dict = pickle.loads(bytes(string_of_bytes_obj, "latin1"))

输出:

>>> print(unpickled_dict)
{'a': 1111, 'b': 2222}

为什么这个能够工作?!我已经花了两个小时试图弄清楚。其他地方都没有答案! - user3513243

0

你需要将它作为字符串的原因是什么?如果你只是想将它写入文件,你可以使用'wb'而不是'w'。(https://pythontips.com/2013/08/02/what-is-pickle-in-python/

import pickle

mydict = { 'a': 1111, 'b': 2222 }
dumped = pickle.dumps(mydict)
string_of_bytes_obj = str(dumped) # Deliberate string representation for this quick example. 

unpickled_dict = pickle.loads(dumped) 

很不幸,这不是我的文件,我只是处理我所接收到的内容! - jehad

0
首先,我不会使用pickle来序列化数据,而是使用Json。
我的解决方案使用了pickle。
import pickle

mydict = { 'a': 1111, 'b': 2222 }
string_of_bytes_obj = pickle.dumps(mydict) # Deliberate string representation for this quick example.
print(string_of_bytes_obj)
unpickled_dict = pickle.loads(string_of_bytes_obj)
print(unpickled_dict)

但是使用 JSON

import json

mydict = { 'a': 1111, 'b': 2222 }
string_of_bytes_obj = json.dumps(mydict) 
print(string_of_bytes_obj)
unpickled_dict = json.loads(string_of_bytes_obj)
print(unpickled_dict)

我强烈建议您使用JSON序列化您的数据


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接