在Python 3中的动态导入和相对导入

5 浏览
0 Comments

在Python 3中的动态导入和相对导入

我有一个使用Python 3编写的项目,其中我从磁盘动态导入模块,使用imp.load_module。但是,我遇到了一个问题,当相对导入发生在动态导入的模块内部时,相对导入失败。\n根据我的阅读,我得出结论,当确定导入路径时,默认导入器只使用__file__,__path__,__package__和__name__。然而,我在下面的代码中验证了这些内容,但在动态导入时仍然失败。(在解释器中导入并更新sys.path时可以正常工作)\n# 文件结构:\n# [根目录]\n# ├─ __init__.py\n# ├─ board.py\n# └─ test.py\n# board.py的内容:\nimport os, sys\nimport root # 已导入...只需要一个引用\nROOT_DIR = os.path.dirname(root.__file__)\nassert root is sys.modules[\'root\']\nassert root.__package__ is None\nassert root.__name__ == \'root\'\nassert root.__file__ == os.path.join(ROOT_DIR, \'__init__.py\')\nassert not hasattr(root, \'__path__\')\nxx = object()\nassert xx is sys.modules[\'root.board\'].xx\nassert __package__ is None\nassert __name__ == \'root.board\'\nassert __file__ == os.path.join(ROOT_DIR, \'board.py\')\nassert not hasattr(sys.modules[\'root.board\'], \'__path__\')\nassert os.path.isfile(os.path.join(ROOT_DIR, \'test.py\'))\nfrom . import test # ImportError(\'无法导入名称test\',)\n但是,如果我在失败的导入之前修改sys.path并重新导入当前包,它就可以正常工作:\noldroot = root\ndel sys.modules[\'root\']\nsys.path.append(os.path.dirname(ROOT_DIR))\nimport root\nfrom . import test # 这里没有错误\n而且,上述四个重要属性在新旧包中是相同的:\nassert oldroot.__package__ == root.__package__\nassert oldroot.__name__ == root.__name__\nassert oldroot.__file__ == root.__file__\nassert not hasattr(root, \'__path__\')\n这意味着__package__,__name__,__file__和__path__并不能完全解释问题。Python还使用其他属性来定位导入吗?我忽视了什么导致导入失败的问题?

0
0 Comments

在Python 3中,出现了"Dynamic imports + relative imports in Python 3"的问题。这个问题的原因是在使用imp.load_module()时,缺少root.__path__值,这意味着Python不将root视为一个包。此外,两个load_module()调用都是使用类型值1(模块)进行的,而不是第一个调用的类型为5(包),这也是非常可疑的。解决这个问题的方法是使用imp.find_module()来确定imp.load_module()调用的正确输入。对于一个包,imp.load_module()的输入应该类似于上述代码中的示例。虽然问题的提问者并没有使用load_module,而是手动解决了所有问题,但是这个答案听起来非常有希望。原因是imp.get_suffixes()中并没有列出类型5,但是load_module确实可以处理这种类型。最后,问题的提问者尝试了这个方法,并且成功解决了问题。答案的提供者解释说,imp.get_suffixes()只涵盖了Python源代码和字节编译文件,而C扩展、内置模块、包目录、冻结模块等有着自己的类型标志。并且load_module是设计用于与find_module配合使用的,PEP 302中有关于这些细节的详细说明。

0