【问题标题】:Same-directory import works when called from outside but not from inside从外部调用但不能从内部调用时,同目录导入有效
【发布时间】:2022-06-13 17:41:26
【问题描述】:

我有结构

main.py                  from mymodule import a; a.A()
mymodule/
mymodule/__init__.py     (empty)
mymodule/a.py                                       # works when called from main.py, fails when called alone
mymodule/b.py            class B: pass
mymodule/c.py            class C: pass
mymodule/test.py         from .a import A; A()      # failing when called alone

a.py 中有:

from .b import B
from .c import C

class A:
    def __init__(self):
        self.b = B()
        self.c = C()

if __name__ == '__main__':
    A()

调用main.py 效果很好。它调用a.py 调用from .b import B

但单独调用 a.py 失败同样 from .b import B 与:

ImportError: 尝试在没有已知父包的情况下进行相对导入

我已经阅读了Relative imports in Python 3 和许多类似的问题,例如How to import the class within the same directory or sub directory?,但这里这个问题是针对:

为什么从main.py 调用a.pyfrom .b import B 会成功,而单独从a.py 调用或调用test.py 时会失败?

如何能够在与a.py 相同的目录中拥有test.py 并能够导入后者?(没有sys.path.append hacks)

【问题讨论】:

  • “单独调用 a.py”是什么意思?你到底是做什么的?
  • @9769953 我的意思是:cd mymodule; python3 test.py; python3 a.py
  • 不要像脚本一样执行模块。模块应该被导入,而不是运行。除非您将它们设为可执行模块,但即便如此,它们也应该以不同的方式“运行”。
  • @9769953 1/2 我最初并没有特别想把它变成一个模块,我更喜欢一切都是“脚本”。但我创建了一个模块,因为它是从同一目录和/或子目录导入另一个 .py 文件的唯一非 sys-path-hack 选项。
  • @9769953 2/2 但是即使是在一个模块中,有一个像test.py这样的脚本来做一个模块特性的demo也是有意义的,并且这个与模块本身在同一个文件夹中

标签: python import python-import


【解决方案1】:

我在相对进口方面遇到过类似的问题。我创建了一个名为 ultraimport 的新导入库,它允许在 Python 中进行基于文件系统的导入。

ultraimport 不关心父包,只会导入文件系统中的任何文件。

在您的 a.py 中,您可以简单地使用:

import ultraimport
B = ultraimport('__dir__/b.py', 'B')
C = ultraimport('__dir__/c.py', 'C')

ultraimport 将始终能够导入文件,无论您如何启动 Python,或者您当前的工作目录是什么,或者您的顶级模块是什么,等等。它也不会使用任何 sys.path hack,也不会改变你的系统路径。它使用自己的加载器。

注意:这个新库是实验性的,我正在寻找有关它如何执行的反馈。它对我有用,但尚未经过广泛测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-30
    • 2023-04-03
    • 2020-02-27
    • 2014-10-01
    • 2019-06-25
    • 1970-01-01
    • 2018-02-28
    相关资源
    最近更新 更多