0

external使用するすべてのレシピとサードパーティのパッケージを含むパッケージをプログラムに追加したいと考えています。バージョンの非互換性は言うまでもなく、(私を含む) 誰にもこれらのパッケージのインストールを強制したくありません。それらを独自のサブフォルダーに入れて使用したいだけです。もちろん、それらはさまざまなソースから来ています。

フォルダー構造は次のようになります。

| main.py
|---[external]
    |---[networkx]
    |   | ...
    |---[xlrd]
    |   | ...
    | __init__.py
    | recipe1.py
    | recipe2.py

私のプログラムでは、次の方法でパッケージとレシピに到達したいと考えています。

import external
import external.xlrd
from external import networkx as nx
import external.recipe1
from external import recipe2 as magic
from external import *

ただし、すべてのパッケージには絶対インポートが含まれている可能性があり、 が空の であるとImportError仮定して結果が生じる可能性があります。external__init__.py

>>> import external.networkx
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".\external\networkx\__init__.py", line 46, in <module>
    from networkx import release
ImportError: No module named 'networkx'

このような外部パッケージを簡単に作成する方法はありますか?

4

1 に答える 1

0

これを行う関数を作成しました。あなたがする必要があるのは、次の行を__init__.py外部フォルダーの に置くことだけです:

__all__ = import_all(__path__)

この関数は、一般に、ネストされている場合でも、すべてのサブモジュールをインポートするために使用できます。これを__init__.py関係するすべてのものに配置してください。

質問に対するよりクリーンな解決策を知っている場合は、私たちと共有してください! 私は自分の答えを受け入れません。

from os import listdir
from os.path import abspath, basename, exists, isdir, join, \
    relpath, sep, splitext
from sys import path

def import_all(path__here):
    """Imports all subpackages and submodules, excluding .py
files starting with an underscore. The directories have to
have an __init__.py to get imported.

Add this line to the __init__.py:
    __all__ = import_all(__path__)"""
    result, packagepath = [], relpath(path__here[0])
    for e in listdir(packagepath):
        mod_path = join(packagepath, e)
        mod_name = splitext(basename(e))[0]
        file_to_import = (e.endswith(".py")
            and not mod_name.startswith("_"))
        dir_to_import = (isdir(mod_path)
            and exists(join(mod_path, "__init__.py")))
        if not file_to_import and not dir_to_import:
            continue
        im_str = ".".join(mod_path.split(sep)[:-1] + [mod_name])
        try:
            __import__(im_str)
        except ImportError as err:
            # In case of a subpackage countains absolute imports
            # assuming it is in the root, we put it into the
            # system path and try again.
            if abspath(packagepath) not in path:
                path.insert(0, abspath(packagepath))
                __import__(im_str)
            else:
                raise err from None
        result.append(mod_name)
    return result
于 2013-10-10T09:08:17.093 に答える