わかった; IMO これはグロスで毛むくじゃらのダーク マジックです。おそらく絶対に使用すべきではありませんが、特に本番コードでは使用しないでください。ただし、好奇心のためだけに興味深いものです。
PEP 302で説明されているメカニズムを使用してカスタム インポーターを作成でき、さらに Doug Hellmann のPyMOTW: Modules and Importsで説明されています。これにより、考えていたタスクを達成するためのツールが得られます。
好奇心が強いという理由だけで、そのようなインポーターを実装しました。基本的に、クラス変数を使用して指定したモジュールの場合、コードが評価される前に、インポートされたモジュールの にカスタム__chatty_for__
型が変数として挿入されます。問題のコードが独自の を定義している場合、それはインポーターによって事前に挿入されたものを置き換えます。このインポーターがモジュールに何をするかを慎重に検討する前に、このインポーターをモジュールに適用することはお勧めできません。__metaclass__
__dict__
__metaclass__
私は多くのインポーターを書いていないので、これを書いている間に 1 つ以上のばかげたことをしたかもしれません。誰かが実装で見逃した欠陥/コーナーケースに気付いた場合は、コメントを残してください.
ソースファイル 1:
# foo.py
class Foo: pass
ソースファイル 2:
# bar.py
class Bar: pass
ソースファイル 3:
# baaz.py
class Baaz: pass
そしてメインイベント:
# chattyimport.py
import imp
import sys
import types
class ChattyType(type):
def __init__(cls, name, bases, dct):
print "Class init", name
super(ChattyType, cls).__init__(name, bases, dct)
class ChattyImporter(object):
__chatty_for__ = []
def __init__(self, path_entry):
pass
def find_module(self, fullname, path=None):
if fullname not in self.__chatty_for__:
return None
try:
if path is None:
self.find_results = imp.find_module(fullname)
else:
self.find_results = imp.find_module(fullname, path)
except ImportError:
return None
(f,fn,(suf,mode,typ)) = self.find_results
if typ == imp.PY_SOURCE:
return self
return None
def load_module(self, fullname):
#print '%s loading module %s' % (type(self).__name__, fullname)
(f,fn,(suf,mode,typ)) = self.find_results
data = f.read()
if fullname in sys.modules:
module = sys.modules[fullname]
else:
sys.modules[fullname] = module = types.ModuleType(fullname)
module.__metaclass__ = ChattyType
module.__file__ = fn
module.__name__ = fullname
codeobj = compile(data, fn, 'exec')
exec codeobj in module.__dict__
return module
class ChattyImportSomeModules(ChattyImporter):
__chatty_for__ = 'foo bar'.split()
sys.meta_path.append(ChattyImportSomeModules(''))
import foo # prints 'Class init Foo'
import bar # prints 'Class init Bar'
import baaz