【问题标题】:Python: How do I import modules without python-filename as submodule?Python:如何导入没有 python-filename 的模块作为子模块?
【发布时间】:2018-01-11 13:35:44
【问题描述】:

说明

假设,我有一个结构如下的包:

package-folder
  |_ mypackage
     |_ __init__.py
     |_ module1.py
  setup.py

__init__.py 为空且

module1.py:

def do_stuff():
    print('Did stuff.')

setup.py 包含用于制作包的常用上下文,可以使用pip install -e pkgpath 在本地系统上安装。

script.py 中,我必须这样做:

import mypackage as abbr

abbr.module1.do_stuff()
# output: Did stuff.

我想要的电话是:

abbr.do_stuff()
# output: Did stuff.

问题

  1. 如何“组织”我的包,以便可以直接从 abbr.function() 调用 module1.py 中的函数?需要更改哪些代码?
  2. 如果包增长,这个组织有用吗?因此目录将充当结构元素,而 python 文件只是在其中组织我的函数的胶囊?
  3. 在模块和子模块中组织功能的最佳方式是什么?

进一步的想法

  • 是否有充分的理由不在每个可从模块中使用的 python 文件中设置一个函数? (并且与文件同名)
  • 我想,我将不得不修改我的__init__.py-文件,但我不知道怎么做。

关于问题 2 的说明

package-folder
|_ mypackage
   |_ __init__.py
   |_ module1.py #with function do_stuff1()
   |_ subpackage
      |_module2.py #with function do_stuff2()
setup.py

调用应该是:

abbr.do_stuff1()
abbr.subpackage.do_stuff2()

不是

abbr.module1.do_stuff1()
abbr.subpackage.module2.do_stuff2()

【问题讨论】:

    标签: python python-3.x module python-import


    【解决方案1】:

    你已经很接近答案了,你只需要从__init__.py导入方法。

    您还可以添加特殊变量__all__,它是用户可以在该文件中找到的变量/函数/等的列表。

    __init__.py@mypackage

    from .module1 import do_stuff1
    
    __all__ = ['do_stuff1']
    

    __init__.py@subpackage

    from .module2 import do_stuff2
    
    __all__ = ['do_stuff2']
    

    编辑:

    要让您的顶级包导入所有子包符号,您可以将__init__.py @mypackage 更改为:

    import pkgutil
    
    from .module1 import do_stuff1
    
    __all__ = ['do_stuff']
    
    for loader, name, is_pkg in  pkgutil.walk_packages(__path__):
        module = loader.find_module(name).load_module(name)
        __all__.extend(module.__all__)
        for var in module.__all__:
            globals()[var] = getattr(module, var)
    

    那么你不仅可以拨打abbr.subpackage.do_stuuf2(),还可以拨打abbr.do_stuuf2()

    【讨论】:

    • 您的解决方案有效,关于问题 1!伟大的!但这不会有点乱,有一个“大”的包裹吗?难道没有更好的方法来做到这一点吗?另外,在here 中建议了一段代码,它应该加载“所有”子模块,但我无法让它工作。除此之外,一些“指南”建议您最好将 init.py 留空。最后评论:但是“最好”的方法是什么?
    • 我不会考虑将 __init__.py 留空作为推荐,它更多是您拥有的选择,但它为您提供了一种非常强大的方式来提供简单的对象访问,同时保持代码有条理的方式。我确实在某些__init__.py 中使用脚本而不是手动导入,但只是太扁平的子包,这是能够做到abbr.do_stuff2()
    • 你能给出一个示例脚本吗?
    • @Laenan 我现在没有脚本的副本,但我基本上遍历了所有子包(目录),将所有子包(目录)导入到它们的 all 变量中进入主包。
    • @Laenan 我在我的答案中添加了一个未经检查的脚本,检查它是否适合你。它基本上会在子包的__all__ 变量中获取所有内容,也将放在包__all__ 中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2022-07-26
    • 1970-01-01
    相关资源
    最近更新 更多