1

当 JSON 尝试使用 dict 中编码的类信息解码我的序列化自定义类时,我遇到了问题。我会尽量提供尽可能多的信息,所以请多多包涵。

我正在使用此处提供的优秀教程作为参考。我指的是详细说明为您自己的类编写编码/解码的部分。

我的包模块结构部分如下:

+--- PyDev Project
    +-- src
        +-- astar
        |    +-- __init__.py
        |    +-- astar.py
        +-- common
        |    +-- __init__.py
        |    +-- service.py
        |    +-- graph.py
        |    +-- vertex.py

这些模块中的每一个都有自己的类。我在common.service模块中序列化Service类的对象。这基本上是通过 Pyro 连接使用的。

序列化代码为:

def convert_to_builtin_type(obj):
    print('default(', repr(obj), ')')
    # Convert objects to a dictionary of their representation
    d = { '__class__':obj.__class__.__name__, 
          '__module__':obj.__module__,
        }
d.update(obj.__dict__)
return d

反序列化代码为:

def dict_to_object(self, d):
    if '__class__' in d:
        class_name = d.pop('__class__')
        module_name = d.pop('__module__')
        # module = __import__(module_name)
        module = import_module(module_name)
        print('MODULE:', module)
        class_ = getattr(module, class_name)
        print('CLASS:', class_)
        args = dict( (key.encode('ascii'), value) for key, value in d.items())
        print('INSTANCE ARGS:', args)
        inst = class_(**args)
    else:
        inst = d
    return inst

该问题在反序列化期间发生。局部变量值是:

class_ = <module 'common.Service' from path-to-file.py>
class_name = 'Service'
module = <module 'common' from path-to-__init__.py>
module_name = 'common.Service'

失败的原因是因为class _ 返回的是 package.module 值,而不是该模块内的类名。从技术上讲,_ 应该包含 common.service.Service,这是实际的类。因此,最后一条语句inst = class (**args)_ 因“TypeError: module object not callable”错误而失败。

我知道import或 importlib.import_module 都导入了那个顶级模块,但就我而言,我如何进入二级模块中的一个类?从技术上讲,第二级是模块,第一级是包,所以我需要 pkg.module 中的一个我无法访问的类。

我希望这个问题是有道理的,并且有足够的研究表明。如果需要澄清,我有更多信息。

编辑:用户建议解决了问题。

def dict_to_object(self, d):
    if '__class__' in d:
        class_name = d.pop('__class__')
        module_name = d.pop('__module__')
        # module = __import__(module_name)
        __import__(module_name)
        module = sys.modules[module_name]
        print('MODULE:', module)
        class_ = getattr(module, class_name)
        print('CLASS:', class_)
        args = dict((key, value) for key, value in d.items())
        print('INSTANCE ARGS:', args)
        inst = class_(**args)
    else:
        inst = d
    return inst
4

1 回答 1

1

想法:

  1. 可能是您的问题出在这一行:

    import_module(module_name)
    

    重新考虑您传递给该函数的参数。

  2. 知道泡菜序列化程序它会执行以下操作而不是import_module

    import sys
    __import__(module_name)
    module = sys.modules[module_name]
    
  3. 在 Python 3 中也尝试使用obj.__class__.__qualname__. 它包括模块名称和嵌套类。

    class X:
         class Y: pass # __qualname__ includes X.Y
    
  4. 如果您之后发布工作代码,我会很好,因为这对很多人来说可能是个问题。

于 2014-01-24T12:32:25.920 回答