如何在包里面引用Python中的顶级模块?

hll*_*lau 19 python module packages

在下面的层次结构中,是否有一种方便且通用的方法可以在下面的所有.py文件中使用通用术语来引用top_package?我想有一个一致的方法来导入其他模块,所以即使"top_package"更改名称没有任何中断.

我不赞成使用像"..level_one_a"这样的相对导入,因为相对路径将与下面的每个python文件不同.我正在寻找一种方式:

  1. 每个python文件可以对包中的同一模块使用相同的import语句.
  2. 在包中的任何.py文件中对"top_package"的解耦引用,因此无论名称"top_package"如何变化,都没有中断.

    top_package/
      __init__.py
      level_one_a/
        __init__.py
        my_lib.py
        level_two/
          __init__.py
          hello_world.py
      level_one_b/
        __init__.py
        my_lib.py
      main.py
    
    Run Code Online (Sandbox Code Playgroud)

jco*_*ado 13

这应该做的工作:

top_package = __import__(__name__.split('.')[0])
Run Code Online (Sandbox Code Playgroud)

这里的技巧是,对于每个模块,__name__变量包含由点分隔的模块的完整路径,例如,top_package.level_one_a.my_lib.因此,如果要获取顶级包名称,只需获取路径的第一个组件并使用它进行导入即可__import__.

尽管仍然调用用于访问包的变量名称top_package,但您可以重命名包,如果仍然可以.


ekh*_*oro 8

将您的包和main脚本放入外部容器目录中,如下所示:

container/
    main.py
    top_package/
        __init__.py
        level_one_a/
            __init__.py
            my_lib.py
            level_two/
                __init__.py
                hello_world.py
        level_one_b/
            __init__.py
            my_lib.py
Run Code Online (Sandbox Code Playgroud)

当main.py运行时,它的父目录(container)将被自动添加到开始sys.path.由于top_package现在位于同一目录中,因此可以从包树中的任何位置导入它.

所以hello_world.py可以level_one_b/my_lib.py像这样导入:

from top_package.level_one_b import my_lib
Run Code Online (Sandbox Code Playgroud)

无论容器目录的名称是什么,或者它位于何处,导入都将始终使用此安排.

但请注意,在您的原始示例中,top_package它可以轻松地充当容器目录本身.所有你需要做的就是删除top_package/__init__.py,你将有效地保持相同的安排.

之前的import语句将更改为:

from level_one_b import my_lib
Run Code Online (Sandbox Code Playgroud)

如果你愿意,你可以自由重命名top_package.