10

この SO questionとやや似たアプローチで、を介していくつかのインポートフックをセットアップしようとしています。このために、上記のリンクで説明されているように、 2 つの関数を定義する必要があります。ここに私の機能があります、sys.meta_pathfind_moduleload_moduleload_module

import imp

def load_module(name, path):
    fp, pathname, description = imp.find_module(name, path)

    try:
        module = imp.load_module(name, fp, pathname, description)
    finally:
        if fp:
             fp.close()
    return module

PyQt4.QtCoreこれはほとんどのモジュールで問題なく動作しますが、Python 2.7 を使用している場合は失敗します:

name = "QtCore"
path = ['/usr/lib64/python2.7/site-packages/PyQt4']

mod = load_module(name, path)

返す、

Traceback (most recent call last):
   File "test.py", line 19, in <module>
   mod = load_module(name, path)
   File "test.py", line 13, in load_module
   module = imp.load_module(name, fp, pathname, description)
SystemError: dynamic module not initialized properly

同じコードが Python 3.4 でも問題なく動作します (ただしimp、非推奨になりつつあり、importlib代わりに使用するのが理想的です)。

これは、SIP 動的モジュールの初期化と関係があると思います。Python 2.7 で試してみるべきことは他にありますか?

注: これはPyQt4との両方に適用されますPyQt5

編集:これは実際にこの質問に関連している可能性があります。

cd /usr/lib64/python2.7/site-packages/PyQt4
python2 -c 'import QtCore'

同じエラーで失敗します。それでも、それを回避する方法が何であるかはわかりません...

Edit2 : @Nikitaの具体的な使用例の要求に従って、私がやろうとしているのはインポートをリダイレクトするimport Aことですimport Bfind_spec/find_moduleこのためには、モジュールの名前を変更してからデフォルトを使用するだけで十分であると実際に考えることができますload_module。ただし、Python 2 のデフォルトの実装がどこにあるのかは不明です。load_module似たようなもので私が見つけた最も近い実装はfuture.standard_library.RenameImport. importlibPython 3 から 2 への完全な実装のバックポートがあるようには見えません。

この問題を再現するインポート フックの最小限の実例は、この要点にあります。

4

2 に答える 2

3

のようなパッケージの一部であるモジュールを見つける場合PyQt4.QtCore、名前の各部分を再帰的に検索する必要があります.。またimp.load_module、そのnameパラメーターは、.パッケージとモジュール名を区切った完全なモジュール名である必要があります。

QtCoreはパッケージの一部であるため、python -c 'import PyQt4.QtCore'代わりに実行する必要があります。モジュールをロードするコードは次のとおりです。

import imp

def load_module(name):
    def _load_module(name, pkg=None, path=None):
        rest = None
        if '.' in name:
            name, rest = name.split('.', 1)
        find = imp.find_module(name, path)
        if pkg is not None:
            name = '{}.{}'.format(pkg, name)
        try:
            mod = imp.load_module(name, *find)
        finally:
            if find[0]:
                find[0].close()
        if rest is None:
            return mod 
        return _load_module(rest, name, mod.__path__)
    return _load_module(name)

テスト;

print(load_module('PyQt4.QtCore').qVersion())  
4.8.6
于 2016-04-28T21:39:26.233 に答える