0

明らかに、Python でクラスを登録することは、メタクラスの主要な使用例です。この場合、現在動的インポートを使用してクラスを作成するシリアライゼーション モジュールがあり、それをファクトリ パターンに置き換えたいと考えています。

したがって、基本的に、これは次のことを行います。

data = #(Generic class based on serial data)
moduleName = data.getModule()
className = data.getClass()
aModule = __import__(moduleName)
aClass = getattr(aModule, className)

しかし、私はこれをしたい:

data = #(Generic class based on serial data)
classKey = data.getFactoryKey()
aClass = factory.getClass(classKey)

ただし、問題があります。ファクトリをメタクラスに依存させると、ファクトリはモジュールがインポートされた後にのみクラスの存在について学習します (たとえば、モジュールのインポート時に登録されます)。したがって、ファクトリを設定するには、次のいずれかを行う必要があります。

  1. 関連するすべてのモジュールを手動でインポートする (これは、メタクラスに自動的に登録させるという目的を実際に無効にします...) または
  2. プロジェクト全体のすべてを自動的にインポートします (これは、信じられないほど不格好でハムフィストだと思います)。

これらのオプションのうち、クラスをファクトリに直接登録することが最善のオプションのようです。私が見ていないより良い解決策を誰かが見つけましたか? 1 つのオプションは、プロジェクト ファイルをトラバースすることによって、ファクトリ モジュールで必要なインポートを自動的に生成することです。

アップデート:

これを締めくくるために、自己回答を投稿しました。入れ子になったサブパッケージ間ですべての Python モジュールをサイクルに決して遭遇しない方法でトラバースする良い方法を誰かが知っているなら、私はこの答えではなくその答えを喜んで受け入れます。私が見ている主な問題は次のとおりです。

\A.py (import Sub.S2)
\Sub\S1.py (import A)
\Sub\S2.py
\Sub\S3.py (import Sub.S2)

S3 をインポートしようとすると、最初に Main をインポートする必要があります (そうしないと、Sub が何かわかりません)。その時点で、A をインポートしようとします。そこにいる間に__init__.pyが呼び出され、A を登録しようとします。この時点で、A は S1 をインポートしようとします。以来、__init__.pySub にヒットし、S1、S2、S3 をインポートしようとします。ただし、S1 は A をインポートしようとしています (インポート中のため、まだ存在しません)。そのため、そのインポートは失敗します。トラバーサルの発生方法を切り替えることができます (つまり、幅を優先するのではなく、深さを優先する) が、同じ問題が発生します。このための優れたトラバーサル アプローチに関する洞察は非常に役立ちます。おそらく 2 段階のアプローチで解決できます (つまり、トラバースしてすべてのモジュール参照を取得してから、フラット バッチとしてインポートします)。しかし、最終段階を処理する最善の方法 (つまり、トラバースが完了したことを知り、すべてをインポートする方法) についてはよくわかりません。私の大きな制限は、処理するスーパー パッケージ (つまり、Sub と A の下に余分なディレクトリ) を持ちたくないということです。それがあれば、トラバーサルを開始できます。しかし、正当な理由もなく、すべてがそれに対して相対的にインポートする必要があります (つまり、余分なディレクトリによってすべてのインポートが長くなります)。これまでのところ、特別な関数呼び出しを sitecustomize.py に追加することが唯一の選択肢のように思えます (とにかく、そのファイルでパッケージ開発のルート ディレクトリを設定します)。

4

1 に答える 1