2

次のようなファイル構造を持つパッケージを開発しています。

test.py
package/
    __init__.py
    foo_module.py
    example_module.py

import packagetest.pyを呼び出す場合、パッケージモジュールを次のように表示します。

>>> vars(package)
mapping_proxy({foo: <function foo at 0x…}, {example: <function example at 0x…})

つまり、すべてのモジュールのメンバーをpackagepackage名前空間に入れたいのですが、モジュール自体を名前空間に入れたくないのです。packageサブパッケージではありません。

私のファイルが次のようになっているとしましょう:

foo_module.py:

def foo(bar):
    return bar

example_module.py:

def example(arg):
    return foo(arg)

test.py:

print(example('derp'))

test.py、example_module.py、および__init __。pyのインポートステートメントを構造化して、パッケージディレクトリの外部(つまりtest.py)およびパッケージ自体の内部(つまりfoo_module.pyおよびexample_module.py)から機能させるにはどうすればよいですか?私が試みるすべてはParent module '' not loaded, cannot perform relative importまたはを与えImportError: No module named 'module_name'ます。

また、補足として(PEP 8による):「パッケージ内インポートの相対インポートはお勧めしません。すべてのインポートには常に絶対パッケージパスを使用してください。PEP328がPython 2.5で完全に実装されている現在でも、そのスタイルは明示的な相対インポートは積極的に推奨されていません。絶対インポートはより移植性が高く、通常は読みやすくなっています。」

Python3.3を使用しています。

4

2 に答える 2

2

パッケージ内のすべてのモジュールのメンバーをパッケージの名前空間に入れたいのですが、モジュール自体を名前空間に入れたくないのです。

Python 2で使用したものを適応させて、プラグインを自動的にインポートし、Python3でも機能するようにすることでそれを実現できました。

一言で言えば、これがどのように機能するかです:

  1. パッケージのファイルは、名前が(アンダースコア)文字__init__.pyで始まるファイルを除いて、同じパッケージディレクトリにある他のすべてのPythonファイルをインポートします。'_'

  2. 次に、インポートされたモジュールの名前空間内の名前をモジュールの名前空間__init__(パッケージの名前空間でもある)に追加します。example_moduleモジュールimport fooをから明示的に作成する必要があることに注意してください.foo_module

__init__.pyこのようにすることの重要な側面の1つは、動的であり、パッケージモジュール名をファイルにハードコードする必要がないことを理解することです。もちろん、これを実現するにはより多くのコードが必要ですが、非常に汎用的で、ほぼすべての(単一レベルの)パッケージで動作できるようになります。新しいモジュールが追加されると自動的にインポートされ、削除されたモジュールはインポートされなくなります。ディレクトリから。

test.py

from package import *

print(example('derp'))

__init__.py

def _import_all_modules():
    """ Dynamically imports all modules in this package. """
    import traceback
    import os
    global __all__
    __all__ = []
    globals_, locals_ = globals(), locals()

    # Dynamically import all the package modules in this file's directory.
    for filename in os.listdir(__name__):
        # Process all python files in directory that don't start
        # with underscore (which also prevents this module from
        # importing itself).
        if filename[0] != '_' and filename.split('.')[-1] in ('py', 'pyw'):
            modulename = filename.split('.')[0]  # Filename sans extension.
            package_module = '.'.join([__name__, modulename])
            try:
                module = __import__(package_module, globals_, locals_, [modulename])
            except:
                traceback.print_exc()
                raise
            for name in module.__dict__:
                if not name.startswith('_'):
                    globals_[name] = module.__dict__[name]
                    __all__.append(name)

_import_all_modules()

foo_module.py

def foo(bar):
    return bar

example_module.py

from .foo_module import foo  # added

def example(arg):
    return foo(arg)
于 2013-01-20T20:17:54.213 に答える
2

from module import nameスタイルのインポートを使用することで、名前空間を乱雑にすることなく、必要な値を取得できると思います。これらのインポートは、あなたが求めているものに対して機能すると思います:

のインポートexample_module.py:

from package.foo_module import foo

のインポート__init__.py:

from package.foo_module import foo
from package.example_module import example

__all__ = [foo, example] # not strictly necessary, but makes clear what is public

のインポートtest.py:

from package import example

test.pyこれは、実行中 (またはパッケージ階層の同じレベルにある何か) の場合にのみ機能することに注意してください。それ以外の場合は、含むフォルダーが python モジュールの検索パスにあることを確認する必要がありますpackage(Python が検索する場所にパッケージをインストールするか、適切なフォルダーを に追加しますsys.path)。

于 2013-01-20T16:55:32.713 に答える