0

サードパーティのアプリケーションで jython を使用しています。サードパーティのアプリケーションには、いくつかの組み込みライブラリがありますfoo。いくつかの (単体) テストを行うために、アプリケーションの外部でいくつかのコードを実行したいと考えています。はアプリケーションにバインドされているためfoo、独自のモック実装を作成することにしました。

ただし、問題が 1 つあります。クラスが Java にあるのに、モック クラスを Python に実装しました。したがって、彼らのコードを使用するにはimport foo、 foo がその後のモッククラスです。ただし、このように python モジュールをインポートすると、モジュールが名前に関連付けられているfoo.fooため、クラスにアクセスするために記述する必要があります。

便宜上、-class にバインドするように記述できるようにしたいと考えfrom ourlib.thirdparty import foofooます。ただし、各ファイルの読み込みにはかなりの時間がかかるため、すべてのクラスを直接インポートすることは避けたいと思います。fooourlib.thirdparty

Pythonでこれを行う方法はありますか? load_module(私は単にクラスを返すか、私が書いたものを上書きしようとしたインポートフックではうまくいきませんでしたsys.modules(私は両方のアプローチが醜い、特に後者だと思います))

編集

わかりました: ここでは、私たちの lib. thirdparty 内のファイルが単純化されたように見えるものを示します (魔法なし):

foo.py:

try:
    import foo
except ImportError:
    class foo
        ....

実際には、次のようになります。

foo.py:

class foo
    ....

__init__.py in ourlib.thirdparty
import sys
import os.path
import imp
#TODO: 3.0 importlib.util abstract base classes could greatly simplify this code or make it prettier.

class Importer(object):
    def __init__(self, path_entry):
        if not path_entry.startswith(os.path.join(os.path.dirname(__file__), 'thirdparty')):
            raise ImportError('Custom importer only for thirdparty objects')

        self._importTuples = {}

    def find_module(self, fullname):
        module = fullname.rpartition('.')[2]

        try:
            if fullname not in self._importTuples:
                fileObj, self._importTuples[fullname] = imp.find_module(module)

                if isinstance(fileObj, file):
                    fileObj.close()
        except:
            print 'backup'
            path = os.path.join(os.path.join(os.path.dirname(__file__), 'thirdparty'), module+'.py')
            if not os.path.isfile(path):
                return None
                raise ImportError("Could not find dummy class for %s (%s)\n(searched:%s)" % (module, fullname, path))

            self._importTuples[fullname] = path, ('.py', 'r', imp.PY_SOURCE)

        return self

    def load_module(self, fullname):
        fp = None
        python = False

        print fullname

        if self._importTuples[fullname][1][2] in (imp.PY_SOURCE, imp.PY_COMPILED, imp.PY_FROZEN):
            fp = open( self._importTuples[fullname][0], self._importTuples[fullname][1][1])
            python = True

        try:
            imp.load_module(fullname, fp, *self._importTuples[fullname])
        finally:
            if python:
                module = fullname.rpartition('.')[2]
                #setattr(sys.modules[fullname], module, getattr(sys.modules[fullname], module))
                #sys.modules[fullname] = getattr(sys.modules[fullname], module)

                if isinstance(fp, file):
                    fp.close()

                return getattr(sys.modules[fullname], module)



sys.path_hooks.append(Importer)
4

1 に答える 1

0

import他の人が指摘したように、ステートメント自体がそのための構文を持っていることは、Pythonでは非常に単純なことです。

from foo import foo as original_foo、たとえば - またはimport foo as module_foo

注目すべき興味深い点は、importステートメントがローカル コンテキストでインポートされたモジュールまたはオブジェクトに名前をバインドすることです。ただし、ディクショナリsys.modules (moduels sys of course), is a live reference to all imported modules, using their names as a key. This mechanism plays a key role in avoding that Python re-reads and re-executes and already imported module , when running (that is, if various of yoru modules or sub-modules import the samefoo` モジュールでは、一度だけ読み取られます。その後のインポートでは、sys.モジュール)。

そして -- 「import...as」構文を除けば、Python のモジュールは別のオブジェクトにすぎません。実行時にモジュールに他の名前を割り当てることができます。

したがって、次のコードも完全に機能します。

import foo
original_foo = foo
class foo(Mock):
   ...
于 2012-09-10T13:56:09.710 に答える