web-dev-qa-db-ja.com

Pythonの「PEP-302新しいインポートフック」の経験

私はRuby(CRuby)の開発者の1人です。現在、Ruby 2.0リリース(2012年2月リリース予定))に取り組んでいます。

Pythonには "PEP302:New Import Hooks" (2003):

このPEPは、Pythonインポートメカニズムのより良いカスタマイズを提供するインポートフックの新しいセットを追加することを提案します。現在のimportフックとは対照的に、新しいスタイルのフックを既存のスキームに挿入できるため、モジュールの検索方法とロード方法をより細かく制御できます。

Ruby 2.0(CRuby 2.0)にPEP302に類似した機能を導入することを検討しています。Matzを説得できる提案をしたいと思います。現在、CRubyは標準のファイルシステムからのみスクリプトをロードできます仕方。

PEP 302についての経験または考慮事項がある場合は、共有してください。

例:

  1. それは素晴らしいスペックです。変更する必要はありません。
  2. ほぼ良好ですが、この問題があります...
  3. 2003年に戻ることができたら、仕様を次のように変更します。
41
Koichi Sasada

私はPythonのrunpyモジュールのメンテナーであり、現在のインポートシステムのメンテナーの1人です。私たちのインポートシステムは非常に柔軟ですが、いくつかの微調整を行わずに卸売りを採用しないことをお勧めします。後方互換性の懸念により、通常必要となるよりも厄介なことがたくさんあります。

Python=でPEP 302を使用して問題が発生するのは、コアインポートシステムを使用するまでにかかった時間です。10年の大半は、インポートフックで複雑なことをしている人なら誰でも1つはPEP 302に準拠したローダー(Zipインポートなど)を処理し、もう1つは標準のファイルシステムベースのインポートメカニズムを処理します。PEP302ローダーを処理すると、インポートされたモジュールも処理されます。標準のファイルシステムインポートメカニズムを使用して、回避できる場合はその間違いを繰り返さないようにしてください。

PEP 420(Python 3.3で実装)は、プロトコルにいくつかの追加を行って、インポーターが名前空間パッケージに部分を提供できるようにします。また、Finder API定義の命名問題を修正します(誤って名前が付けられた「より正確な「find_loader」を備えたfind_module」。これは、うまくいけば、3.3rc1が数週間で転がる頃には、すべて言語仕様でより明確に文書化されているはずです。

もう1つの注目すべき問題は、PEP 302に具体的に記載されているアプローチでは、プロセスのグローバルな状態が多すぎることです。そのパスをたどらないでください。状態をより一貫性のあるオブジェクトモデルにカプセル化して、他のモジュールを選択的にインポートする方が少し簡単になるようにしてください(C拡張モジュールは、そのようなカプセル化を完全に効果的にするが、ある程度のカプセル化を行う場合も同様です)役立ちます)。

PEP 406(http://www.python.org/dev/peps/pep-0406/)は、改良された状態のカプセル化によるPythonのアプローチの後方互換性のある進化について説明しています。ただし、最初からカプセル化された状態モデルがある場合は、それに応じてAPIを定義し、インポーターとローダーがグローバル状態にアクセスするのを回避できます(アクティブエンジンへの参照が渡されません)。

PEP 302のもう1つの欠けている部分は、そのインポーターによって提供されるモジュールに対してイテレーターをインポーターに要求する機能です(これは、フリーズユーティリティや、ドキュメント文字列を抽出する自動ドキュメントユーティリティなどに必要です)。信じられないほど便利なので、最初から標準化したほうがいいでしょう: http://docs.python.org/dev/library/pkgutil#pkgutil.iter_modules (おそらく最後に、これをPython 3.4)で正式に指定されたAPIに昇格させます。

そして、私の最後のコメントは、インポートシステムとローダーオブジェクトの間の責任の分担について詳しく調べる必要があるということです。特に、「load_module」APIを「init_module」と「exec_module」のステップに分割することを検討してください。これにより、ローダーがインポート状態と直接対話する必要がある度合いを最小限に抑えることができます。

PEP 302とimportlibは、より柔軟なインポートシステムの優れた出発点ですが、回避すべき価値のある間違いは間違いありません。

47
ncoghlan

Ncoghlanの隣にいる私は、Pythonのインポートシステムのもう1つのメンテナーであり、現在の実装であるimportlib(http://docs.python.org/dev/py3k/library/importlib.html)の作成者です。ニックが同意するすべてのことを言っているので、追加の情報を追加したいだけです。

まず、直接PEP 302に過度に依存しないでください。代わりに、抽象基本クラスなどに関してimportlibが提供するものを確認してください。下位互換性のために、事物はPEP 302と互換性がなければなりませんでしたが、真の柔軟性のサポートを具体化するための独自のAPI。

もう1つの重要な点は、開発者に2つの柔軟性を与えることです。 1つは、個別のファイルとしてファイルシステムに直接以外の方法でコードを格納する機能です(これをインポートの場合はstorage back-endと呼びます)。これにより、Zipファイル、sqliteデータベースなどにコードを置くことができます。他のサポートでは、制御をコードの前処理または後処理に何らかの方法で許可します。 Quixote(https://www.mems-exchange.org/software/quixote/)と、変数に割り当てられていない文字列リテラルの代替使用は、サポートがはるかに簡単になります。

後者が必要になることはめったにありませんが、前者はサポートについて心配する必要がある場所です。そして、ここでファイルシステムインタラクションAPIを実質的に再定義することになります。一部の人々は、コードとともにファイルとして保存されたアセットを必要とするため、ファイルの読み取り、ファイルの検出などを行うための適切な方法を提供する必要があります。使用可能なデータファイルを検出し、それらを一覧表示するために、APIの一部を実装する必要があります。 。

ただし、コード固有のAPIも必要です。 Nickが述べたように、パッケージがどのモジュールに含まれているかなど、ファイル固有ではないモジュールを検出するには、APIが必要になります。ファイルの概念を抽出したモジュールを処理するためのAPIを持つという奇妙な二面性がありますが、ファイルのようなアセットデータにアクセスするためのAPIを提供する必要があります。そして、重複を避けるためにもう一方に関して実装しようとするとすぐに、水は本当にあいまいになります(つまり、人々は、パスが実際のパスではない可能性があるという事実に注意を払わずに、予期されるファイルパス構造に依存することになります)。これは、ファイルだけでなく、コードを含むzipファイル用であるためです。 IOWでは、2つの類似したAPIを実装する必要がありますが、長期的にはそれを使用する方がよいでしょう。

Nickが言ったように、私たちのソリューションは良い出発点ですが、APIをゼロから設計していた場合、今日の方法では実現できません。

28
Brett Cannon