【问题标题】:Package import of function with same name as module causing ghosting with relative imports与模块同名的函数的包导入导致相对导入出现重影
【发布时间】:2018-02-06 06:53:28
【问题描述】:

我有一个包foo_package 是这样组织的:

foo/
    setup.py
    README.md
    ...
    foo_package/
        __init__.py
        bar.py
        baz.py

模块bar.py 定义了一个“公共”函数,也称为bar,并且模块和函数都受益于准确命名barbar.py 还定义了一些“私有”辅助函数。

__init__.py 内部,我对bar.bar 进行了顶级导入,这样foo_package.bar 将成为整个包的API。

# __init__.py:
from .bar import bar

但现在我被相对进口咬伤了。

首先,如果我正在调试或在 IPython 之类的交互式提示中工作,那么天真地粘贴 from .bar import bar 是行不通的。我可以通过在 foo_package 中启动 IPython 并改用 from foo_package import bar 来解决这个问题。

但是我怎样才能导入bar 模块 而不是导出的bar 函数呢?例如。

的变体
from foo_package import bar
import foo_package.bar as bar

等等,都导入了函数bar,同时bar.py也包含了对另一个模块的相对导入,比如

# inside bar.py
from .baz import helper_function

然后是平原

import bar

也不行。

bar 模块bar 函数 的包级“重影”是正确的行为。如何在本地开发中(尤其是在 IPython 等交互式环境中)导入 bar 模块 的同时保持这一点?

【问题讨论】:

    标签: python import package relative-import


    【解决方案1】:

    如果您确实有令人信服的理由保留阴影,您可以通过sys.modules 访问模块对象:

    import sys
    import foo_package.bar
    
    bar_module = sys.modules['foo_package.bar']
    

    还有importlib.import_module:

    import importlib
    
    bar_module = importlib.import_module('foo_package.bar')
    

    【讨论】:

    • 无法将相对导入粘贴到例如IPython 也是一个痛点。在设计包时使用显式相对导入有很多好处,但是在开发该包时,您可能想要粘贴代码并以交互方式测试事物。必须调整从被测文件中复制的实际导入语句,以人为地使用sys.modulesimportlib,暂时会增加很多开销。
    • @ely:如果您希望导入无论在哪个模块中运行或是否在__main__ 中运行都一样,那么您需要绝对导入。从它们相对的模块中复制相对导入是行不通的。 (此答案中的任何代码都不是为了复制from .bar import bar 的行为,因为它导入了函数,并且您要求提供模块。如果您想要一个始终导入函数的导入,那就是from foo_package.bar import bar。)
    • 我明白了。我是说我想要我的蛋糕也想吃。我不喜欢从工作目录自动导入相对导入的简单方法。使用显式相对导入有设计上的好处,因为您事先知道该模块不是顶级包。并且与顶级安装模块发生名称冲突的风险较小(尤其是在发布代码后意外)。这是值得的,因此唯一的答案是牺牲这一点并使用绝对导入,这有点令人失望。
    猜你喜欢
    • 2010-11-16
    • 1970-01-01
    • 2014-06-15
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 2011-10-29
    • 2014-01-09
    • 2018-11-25
    相关资源
    最近更新 更多