2

私は(少なくとも今のところは)「モジュールダックタイピング」という名前の新しい手法を試し始めたところです。

例:

メインモジュール

import somepackage.req  ## module required by all others
import abc
import Xyz

モジュールabc

__all__=[]

def getBus():
    """ Locates the `req` for this application """
    for mod_name in sys.modules:
        if mod_name.find("req") > 0:
            return sys.modules[mod_name].__dict__["Bus"]
    raise RuntimeError("cannot find `req` module")

Bus=getBus()

モジュールabcでは、明示的にする必要はありませんimport req。パッケージ階層のどこにあってもかまいません。もちろん、これにはある程度の規律が必要です...

この手法を使用すると、階層内でパッケージを簡単に再配置できます。

私を待っている落とし穴はありますか?例:Python3Kへの移行

更新:さらにテストを行った後、パッケージの依存関係をに直接挿入することに戻りましたsys.path

4

3 に答える 3

4

「req」を含むすべての種類のモジュールがインポートされている可能性があり、それが実際に探しているモジュールであるかどうかはわかりません。

>>> import urllib.request
>>> import tst
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "tst.py", line 12, in <module>
    Bus=getBus()
  File "tst.py", line 9, in getBus
    return sys.modules[mod_name].__dict__["Bus"]
KeyError: 'Bus'

パッケージの要点は、モジュール階層の名前空間があるということです。「任意のパッケージから」モジュール名を検索すると、競合する名前のモジュールが含まれているライブラリをユーザーがインポートした場合に、コードがランダムに破損します。

于 2010-02-23T22:18:01.353 に答える
1

この手法は危険であり、エラーが発生しやすくなります。誰かが新しいものをインポートしてsomething.req、紛らわしい、はるかに遠いエラーが発生する日まで、テストで機能する可能性があります。(これは最良のシナリオです。現在の実装は他の多くのモジュールにジャンプします。)パッケージを再構築する場合、魔法を使わずに自動化された方法でコードを変更するのは簡単です。Pythonは、あらゆる種類の魔法の動的なことを可能にしますが、それは私たちがすべきだという意味ではありません。

于 2010-02-23T22:28:17.200 に答える
0

これはダックタイピングのようなものだと思います。また、「バス」よりも一意の識別子を使用することをお勧めします

def getBus():
    """ Locates the Bus for this application """
    for mod in sys.modules.values():
        if hasattr(mod, 'Bus') and type(mod.Bus) is...: # check other stuff about mod.Bus
            return mod.Bus
    raise RuntimeError("cannot find Bus")
于 2010-02-24T01:09:28.110 に答える