python 複数 サブディレクトリ内の異なるファイルからのクラスのインポート




python モジュール 作成 (4)

ここで私が協力している構造は次のとおりです。

directory/
          script.py
          subdir/
                 __init__.py
                 myclass01.py
                 myclass02.py

私がしたいのは、 myclass01.pymyclass02.py定義されたクラスをscript.pyでインポートすることです。 私が行った場合:

from subdir.myclass01 import *

myclass01.py定義されているクラスでmyclass01.pyます。 しかし、このソリューションでは、 subdir内の異なるファイルに多くのクラスが定義されていて、それらのすべてをインポートしたい場合は、各ファイルに1行を入力する必要があります。 このためのショートカットが必要です。 私は試した:

from subdir.* import *

しかしそれはうまくいかなかった。

編集 :ファイルの内容は次のとおりです。

これは__init__.py (Apalalaが提案したように__all__を使用しています):

__all__ = ['MyClass01','MyClass02']

これはmyclass01.pyです:

class MyClass01:
    def printsomething():
        print 'hey'

これはmyclass02.pyです:

class MyClass02:
    def printsomething():
        print 'sup'

これはscript.pyです:

from subdir import *
MyClass01().printsomething()
MyClass02().printsomething()

これはscript.pyを実行しようとすると得られるトレースバックです:

File "script.py", line 1, in <module>
    from subdir import *
AttributeError: 'module' object has no attribute 'MyClass01'

https://code.i-harness.com


あなたの最善の選択肢は、おそらく最高のスタイルではないが、すべてをパッケージのネームスペースにインポートすることです。

# this is subdir/__init__.py
from myclass01 import *
from myclass02 import *
from myclass03 import *

次に、他のモジュールでは、パッケージから直接必要なものをインポートできます。

from subdir import Class1

そこで使われている名前はあなたの質問のディレクトリ構造に表示されている名前とは異なりますが、 名前空間とクラスという質問に対する私の答えを使うことができます。 __init__.py表示されていれば、 usepackage.pyスクリプトはこのように書かれていsubdirpackageはあなたの質問のsubdirにマップされ、 Class1myclass01などにマップされます)。

from package import *

print Class1
print Class2
print Class3

リビジョン(更新済み):

おっと、申し訳ありませんが、私の他の答えのコードでは、あなたが望むことはしません。パッケージサブモジュールの名前を自動的にインポートするだけです。 名前を付けた属性を各サブモジュールからインポートするには、さらにいくつかのコード行が必要です。 パッケージの__init__.pyファイルの修正版です(これはPython 3.4.1でも動作します):

def _import_package_files():
    """ Dynamically import all the public attributes of the python modules in this
        file's directory (the package directory) and return a list of their names.
    """
    import os
    exports = []
    globals_, locals_ = globals(), locals()
    package_path = os.path.dirname(__file__)
    package_name = os.path.basename(package_path)

    for filename in os.listdir(package_path):
        modulename, ext = os.path.splitext(filename)
        if modulename[0] != '_' and ext in ('.py', '.pyw'):
            subpackage = '{}.{}'.format(package_name, modulename) # pkg relative
            module = __import__(subpackage, globals_, locals_, [modulename])
            modict = module.__dict__
            names = (modict['__all__'] if '__all__' in modict else
                     [name for name in modict if name[0] != '_'])  # all public
            exports.extend(names)
            globals_.update((name, modict[name]) for name in names)

    return exports

if __name__ != '__main__':
    __all__ = ['__all__'] + _import_package_files()  # '__all__' in __all__

別の方法として、上記のファイルをパッケージディレクトリにある別の.pyモジュールファイルに入れて、パッケージの__init__.pyから次のように使用することもできます。

if __name__ != '__main__':
    from ._import_package_files import *  # defines __all__
    __all__.remove('__all__')  # prevent export (optional)

ファイルの名前は何でも、 _アンダースコアで始まるものでなければならないので、再帰的にimportしようとはしません。


私はこの簡単な方法を使用します:

  1. ディレクトリをシステムパスに追加してから、
  2. import moduleまたはfrom module import function1, class1からそのディレクトリをfrom module import function1, class1します。

moduleが拡張部分のない*.pyファイルの名前にすぎないことに注意してください。

一般的な例を次に示します。

import sys
sys.path.append("/path/to/folder/")
import module # in that folder

あなたの場合は、次のようなものになります。

import sys
sys.path.append("subdir/")
import myclass01
# or
from myclass01 import func1, class1, class2 # .. etc

from subdir.* import *

このように '*'を 'from'ステートメントの直後に使用することはできません。 あなたは輸入品を明らかにする必要があります。 インポートとパッケージに関するPythonのドキュメントを調べてください。







import