Skip to main content
 首页 » 编程设计

Python pickle 似乎在类内部中断,但在命令行脚本中却没有

2025年05月04日12飞鱼

我一直在尝试从数据库中提取一些词典。我已经恢复使用 marshal 模块,但仍然想知道为什么 pickle 在反序列化某些数据时如此困难。这是一个命令行 python session ,基本上显示了我正在尝试做的事情:

>>> a = {'service': 'amazon', 'protocol': 'stream', 'key': 'lajdfoau09424jojf.flv'} 
>>> import pickle; import base64 
>>> pickled = base64.b64encode(pickle.dumps(a)) 
>>> pickled 
'KGRwMApTJ3Byb3RvY29sJwpwMQpTJ3N0cmVhbScKcDIKc1Mna2V5JwpwMwpTJ2xhamRmb2F1MDk0MjRqb2pmLmZsdicKcDQKc1Mnc2VydmljZScKcDUKUydhbWF6b24nCnA2CnMu' 
>>> unpickled = pickle.loads(base64.b64decode(pickled)) 
>>> unpickled 
{'protocol': 'stream', 'service': 'amazon', 'key': 'lajdfoau09424jojf.flv'} 
>>> unpickled['service'] 
'amazon' 

一切正常,但是当我在一个类的工厂方法中尝试这个时,似乎 pickle.loads 部分出错了。我尝试加载的字符串的 pickle 方式与上述相同。我什至尝试复制在上面的命令行 session 中 pickle 的确切字符串,然后尝试取消 pickle 它,但没有成功。这是后一种尝试的代码:

class Resource: 
 
    _service = 'unknown' 
    _protocol = 'unknown' 
    _key = 'unknown' 
 
    ''' 
    Factory method that creates an appropriate instance of one of Resource’s subclasses based on  
    the type of data provided (the data being a serialized dictionary with at least the keys 'service',  
    'protocol', and 'key').  
    @param resource_data (string) -- the data used to create the new Resource instance.  
    ''' 
    @staticmethod 
    def resource_factory(resource_data): 
        # Unpack the raw resource data and then create the appropriate Resource instance and return.  
        resource_data = "KGRwMApTJ3Byb3RvY29sJwpwMQpTJ3N0cmVhbScKcDIKc1Mna2V5JwpwMwpTJ2xhamRmb2F1MDk0MjRqb2pmLmZsdicKcDQKc1Mnc2VydmljZScKcDUKUydhbWF6b24nCnA2CnMu" #hack to just see if we can unpickle this string 
        logging.debug("Creating resource: " + resource_data) 
        unencoded = base64.b64decode(resource_data) 
        logging.debug("Unencoded is: " + unencoded) 
        unpacked = pickle.loads(unencoded) 
        logging.debug("Unpacked: " + unpacked) 
        service = unpacked['service'] 
        protocol = unpacked['protocol'] 
        key = unpacked['key'] 
 
        if (service == 'amazon'): 
            return AmazonResource(service=service, protocol=protocol, key=key) 
        elif (service == 'fs'): 
            return FSResource(service=service, protocol=protocol, key=key) 

请您参考如下方法:

您的代码有效。你如何测试它?

import logging 
import base64 
import pickle 
class Resource: 
    @staticmethod 
    def resource_factory(resource_data): 
        resource_data = "KGRwMApTJ3Byb3RvY29sJwpwMQpTJ3N0cmVhbScKcDIKc1Mna2V5JwpwMwpTJ2xhamRmb2F1MDk0MjRqb2pmLmZsdicKcDQKc1Mnc2VydmljZScKcDUKUydhbWF6b24nCnA2CnMu" #hack to just see if we can unpickle this string 
        # logging.debug("Creating resource: " + resource_data) 
        unencoded = base64.b64decode(resource_data) 
        # logging.debug("Unencoded is: " + unencoded) 
        unpacked = pickle.loads(unencoded) 
        logging.debug("Unpacked: " + repr(unpacked)) 
        service = unpacked['service'] 
        protocol = unpacked['protocol'] 
        key = unpacked['key'] 
 
logging.basicConfig(level=logging.DEBUG) 
Resource.resource_factory('') 

产量

# DEBUG:root:Unpacked: {'protocol': 'stream', 'service': 'amazon', 'key': 'lajdfoau09424jojf.flv'}