【问题标题】:Easily importing all third-party packages and scripts as a common package?轻松将所有第三方包和脚本导入为通用包?
【发布时间】:2013-10-10 09:08:17
【问题描述】:

我想在我的程序中添加一个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'

有没有一种简单的方法可以制作这样的外部包?

【问题讨论】:

    标签: python python-3.x import


    【解决方案1】:

    我做了一个函数来做这个。你需要做的就是将此行放到外部文件夹的__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
    

    【讨论】:

      猜你喜欢
      • 2017-08-08
      • 1970-01-01
      • 1970-01-01
      • 2017-08-11
      • 2019-06-16
      • 1970-01-01
      • 1970-01-01
      • 2016-04-15
      • 2014-05-11
      相关资源
      最近更新 更多