【问题标题】:Python: Do relative imports mean you can't execute a subpackage by itself?Python:相对导入是否意味着您不能自己执行子包?
【发布时间】:2010-12-07 19:56:03
【问题描述】:

我最近移植了我的 Python 项目以在 Python 3.1 上运行。为此,我必须在我的项目的子模块和子包中采用相对导入的策略。我没有那样做,现在项目本身可以工作,但我注意到我无法执行其中的任何子包或子模块。如果我尝试,我会得到“builtins.ValueError: Attempted relative import in non-package”。我只能导入整个项目。

这正常吗?

【问题讨论】:

    标签: python import python-3.x


    【解决方案1】:

    是的,这很正常。如果你想执行一个也是包一部分的模块(这本身就是一件奇怪的事情),你需要绝对导入。当您执行模块时,从解释器的角度来看,它不是包的一部分,而是__main__ 模块。所以它不会知道相关包在哪里。

    执行此操作的标准方法是在包中包含函数,以及调用函数的单独可执行脚本,因为这使您可以将可执行脚本放在模块之外,例如 /usr/bin

    【讨论】:

    • 哇,我觉得这种哲学很奇怪。例如,我的项目中有一个包life。它的绝对路径是garlicsim.bundled.simulation_packages.life。我希望能够自己运行它,因为它不依赖于garlicsim 中的任何内容。为什么我不能自己运行它?
    • 1.如果它不依赖于garlicsim中的任何东西,那么为什么它在garlicsim中? 2. 为什么不能自己运行?你可以自己运行它,但你需要绝对导入,即from garlicsim.bundled.simulation_packages.life import whatever。 3. 你觉得奇怪的哲学是什么?我没有提到任何哲学,所以我不知道“这个”哲学是什么。
    • 1.它只是捆绑在一起的。但我可以举另一个例子,@ 987654326@,它是garlicsim 所依赖的子包,但它不依赖于garlicsim。 (2) 假设有一天我想将它移动到另一个包中,为什么我不能这样做,而无需大惊小怪地编辑导入行? (3) 也许我应该说“政策”而不是“哲学”。这种态度,能够 (a) 独立执行包,或 (b) 轻松地将其移植到其他包,但不能两者兼而有之
    • 天啊。今天人们反对这些答案是怎么回事? :-) 你不能轻易移动它吗?搜索和替换不是很容易吗?无论如何,您都需要在garlicsim中进行搜索和替换。 --- 没有这样的政策。然而,不可能做你想做的事,但话又说回来,没有令人信服的理由去做。 --- 如果你不同意 Python 3 中相对导入的变化(并且有非常很好的理由改变它)而不是抱怨 Python-dev,并准备好燃烧,:-)
    【解决方案2】:

    您可以使用 python 解释器的 -m 标志来运行子包(甚至是 3.1 中的包)中的模块。

    【讨论】:

    • 我会说你使用-m开关;不是你可以。我喜欢直接调用 python 文件,因为我不需要记住开关,我的 shell 很好地自动完成。
    • 如果您对从子模块运行可执行 python 脚本感兴趣,请查看此答案:stackoverflow.com/a/11537218/730150
    【解决方案3】:

    我有same problem,我认为-m 开关太难了。

    我使用这个:

    try:
        from . import bar
    except ValueError:
        import bar
    
    if __name__ == "__main__":
        pass
    

    【讨论】:

    • 隐式相对导入在 python 2.7 中被弃用和删除。
    • 阿伦,你是对的,但我看不出这会如何改变我的解决方案。这适用于任何 python 2.5-3.1。
    • 不,这在 3.x 中不起作用。它在 2.7+ 中被删除,包括 3.0-3.1。
    • @Arron,您是否尝试过上述代码但运行失败?我猜不是,我确实在 Python 2.6、2.7 和 3.1 上运行过它。您所说的更改仅影响像 import bar 这样的行的行为,这就是我提出这种用法的原因,以说服 Python 如果可能的话更喜欢从当前目录加载 bar 模块。
    • @AaronGallagher,你是什么意思?当然,我可以从主脚本或交互式 shell 中导入名为 bar.py 的工作目录中的文件。我只是不能从模块中做到这一点。
    猜你喜欢
    • 2015-12-15
    • 2013-02-05
    • 2020-07-29
    • 2014-08-15
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    相关资源
    最近更新 更多