已解决:从 python 2 转换为 python 3 时出现 Rect() TypeError

问题描述 投票:0回答:1

在将应用程序从 python 2 转换为 python 3 时,我遇到了最奇怪的错误。 简而言之,该应用程序使用 wxPython 创建一个界面,用户可以在其中在画布上绘制不同的对象,并且当单击对象时,用户可以编辑它们并设置不同的参数。关闭应用程序时可以保存所有这些编辑。此保存是使用 python 的搁置库执行的。

这个应用程序与 python 2 完美配合,但是出于兼容性原因,我试图将其引入 python 3,但问题来了:在 python 3 上,我可以保存所有可能的对象,但是,如果我添加一个特定的对象,由图标组成的只是两个图标之间的一条线,我无法重新打开该项目。我可以添加对象、使用它、更改其设置、保存文件,但我无法重新打开它。

最大的问题是我没有调用堆栈来分析。它只是说它正在尝试解开架子上的物体,我得到的下一个信息是:

File "\Unpickle.py", line 25, in renamed_load
    return RenameUnpickler(file_obj, encoding=encoding).load()
TypeError: Rect(): arguments did not match any overloaded call:
  overload 1: too many arguments
  overload 2: not enough arguments
  overload 3: argument 1 has unexpected type 'float'
  overload 4: argument 1 has unexpected type 'float'
  overload 5: argument 1 has unexpected type 'float'
  overload 6: argument 1 has unexpected type 'float'

真正奇怪的是,如果我打开一个在 python 2 中生成的文件(使用与this非常相似的东西进行转换,我不会收到相同的错误,我可以打开并编辑该文件。但是问题仍然存在当文件关闭并再次重新打开时出现。

这是执行读取的类,它继承自 Unpickler,以便我可以重写 find_class 方法。这个错误的最大问题,真正让我发疯的是,调用堆栈没有告诉我在 unpickle 过程中错误在哪里,并且如果我扫描代码中是否出现 Rect,我找不到任何错误。

class RenameUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        renamed_module = module
        if module == "wx._gdi":
            renamed_module = "wx"
        return super(RenameUnpickler, self).find_class(renamed_module, name)

def renamed_load(file_obj, encoding):
    return RenameUnpickler(file_obj, encoding=encoding).load()

def renamed_loads(pickled_bytes):
    file_obj = io.BytesIO(pickled_bytes)
    return renamed_load(file_obj)

class ShelfFileVO( shelve.DbfilenameShelf ):

    def __init__(self, *args, **kwds):
        kwds[ 'protocol' ] = 2
        shelve.DbfilenameShelf.__init__( self, *args, **kwds )
        self._semaphore = threading.BoundedSemaphore( 1 )
        self.find_globals = None

    def keys(self):
        return [ k.decode() for k in self.dict.keys() ]

    def has_key(self, key):
        return key.encode() in self.dict

    def __contains__(self, key):
        return key.encode() in self.dict

    def get(self, key, default=None):
        #key = key.encode()
        if key in self.dict:
            return self[ key ]
        else:
            return default

    def __getitem__(self, key):
        #key = key.encode()
        if key in list(self.cache.keys()):
            value = self.cache[ key ]
        else:
            f = BytesIO( self.dict[ key ] )
            value = renamed_load(f, encoding='latin1')

解决方案:我已经解决并发布了我的临时解决方案here并且它已在wxPython代码中得到纠正

python-2.7 typeerror wxpython python-3.7
1个回答
0
投票

过去在 Python 2/wxPython-old 中接受浮点数作为输入的所有 wxPython 原语(wx.Rect、wx.Size,还有很多其他)将不再适用于 Python 3/wxPython Phoenix。

您必须调整代码以将浮点数转换为整数,和/或腌制您的东西,以便使用整数参数保存矩形/大小。

如果您的应用程序中没有任何 wx.Rect/wx.Size 对象,您将必须确定您是否在腌制东西的任何地方调用 GetRect() 或 GetSize() 或 GetPosition() 。

© www.soinside.com 2019 - 2024. All rights reserved.