【问题标题】:Is a type assigned to pickled objects?是否为腌制对象分配了类型?
【发布时间】:2021-05-22 00:03:21
【问题描述】:

我正在使用 Python 2.7 解析用于绘图的 GPS 坐标的多层列表。该列表被递归解析,从 sqlite3 中获取,并且在该过程中的某个时间点遇到了一个已被腌制的坐标集。 我需要一种按类型检测它的方法,这意味着当我点击腌制数据时,我需要程序来识别它,解开它并继续递归它。

腌制数据有类型或类吗?到目前为止,我得到的只是元组、字符串或 unicode。我不能假设数据在列表中的某个深度,因为有时一个数据流中有多个坐标集。我只是想使用isinstance 来检测它。

我在解决这个问题上的微弱尝试如下。 (一个问题 - 由于这是一台工作计算机,我无法升级 Python 或使用外部库。)

def plotCoordinates(self, coordinates, lineColor, lineWidth, tags):
    if coordinates is None:
        return

    elif isinstance(coordinates, list):
        if isinstance(coordinates[0], tuple):   # COORDINATE TUPLE INSIDE THIS LIST?
            # FOUND COORDINATES LIST, PLOT IT
            for inx, coordinate in enumerate(coordinates):
                longitude, latitude = coordinate

                if inx == 0:
                    oldLatitude, oldLongitude = latitude, longitude
                else:
                    self.plotLine(oldLatitude, oldLongitude, latitude, longitude, lineColor, lineWidth, tags, 1)
                    oldLatitude, oldLongitude = latitude, longitude

            return

        else:    # JUST AN ORDINARY LIST, RECURSE ON IT
            for item in coordinates:
                self.plotCoordinates(item, lineColor, lineWidth, tags)
            return

    elif isinstance(coordinates, tuple):
        # DIVE DOWN DEEPER INTO THE LIST
        for item in coordinates:
            self.plotCoordinates(item, lineColor, lineWidth, tags)
        return

    # FOUND PICKLED LIST. EXTRACT IT
    elif isinstance(coordinates, str) or isinstance(coordinates, unicode):
        self.plotCoordinates(pickle.loads(coordinates), lineColor, lineWidth, tags)
        return

    else:
        # ERROR, UNKNOWN TYPE
        print coordinates
        print 'TYPE UNDETECTED: ' + str(type(coordinates))
        return

【问题讨论】:

  • pickle.dumps 将简单地返回一个字符串,它是一种二进制序列化格式。 (Python 3 中的 bytes 对象)
  • 是的,当你腌制一个对象时,对象的类型/类是腌制的一部分。未腌制的结果与腌制的对象完全相同。查看腌制文本以了解其完成方式很有启发性。
  • 您始终可以尝试在 try/except 的上下文中解开数据。如果pickle 无法识别它,则会引发异常(然后您可以捕获)。类型检查被认为是 unpythonic 加上反 OOP,“在你跳跃之前寻找”(又名 LBYL)也是如此。

标签: python python-2.7 recursion pickle isinstance


【解决方案1】:

在 Python 2.7 中,type(pickled_object) 将始终为 str。然而,并不是每个str 都是腌制对象。例如isinstance("Hello", str) == True,但"Hello" 不是腌制对象。如果你执行pickle.loads("Hello"),你会得到一个神秘的错误。没有可以使用isinstance 检查的腌制对象的特定类型。腌制对象只是一个字符串,pickle 可以使用loads 将其转换为对象,因为pickle 最初是从使用dumps 的对象创建的。

最pythonic的方法是尝试解开对象,然后让pickle模块在它不能这样做时引发异常(如cmets中提到的martineau)。 pickle 模块是创建所有腌制对象的模块,它可以通过尝试取回原始对象来最好地确定字符串是否是腌制对象。如果它成功了,你就有了一个很好的未腌制对象来绘制。如果它失败了,那么你所拥有的只是一个你不知道该怎么处理的字符串,因为它不是一个腌制的对象。

要实现这一点,在检查 tuple 情况后,在另一个 elif 子句中,执行以下操作:

    elif isinstance(coordinates, str):
        # Strings might be pickled objects, let's see if this one is
        try:
            # Try to unpickle coordinates
            obj = pickle.loads(coordinates)
        except Exception:
            # Coordinates failed to unpickle
            # We cannot plot any coordinates with this input, then
            print coordinates
            print 'String could not be unpickled')
            return
        else:
            # Unpickling created an object, now let's try to plot it
            self.plotCoordinates(obj, lineColor, lineWidth, tags)
            return
    else:
        # ERROR, UNKNOWN TYPE
        print coordinates
        print 'TYPE UNDETECTED: ' + str(type(coordinates))
        return

【讨论】:

  • 这可能会奏效。感谢您的建议!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 2012-04-16
  • 2011-09-26
  • 2014-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多