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 値を返すためです。技術的には、class _ は実際のクラスであるcommon.service.Serviceを保持する必要があります。このため、最後のステートメントinst = class (**args)_ は「TypeError: module object not callable」エラーで失敗しています。

importまたは importlib.import_module の両方がその最上位モジュールをインポートすることは知っていますが、私の場合、第 2 レベル モジュール内のクラスにアクセスするにはどうすればよいですか? 技術的には、2 番目のレベルがモジュールで、1 番目のレベルがパッケージであるため、取得できない 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. pickleシリアライザーを知っていると、代わりに次のことが行われます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 に答える