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