简体   繁体   English

Python 子模块在 python 3.7 但不是 3.6 中正确导入

[英]Python submodule importing correctly in python 3.7 but not 3.6

I have a directory structure as follows:我的目录结构如下:

test/
  __init__.py
  m1/
    __init__.py
    f1.py
    f2.py

test/__init__.py is empty. test/__init__.py是空的。

test/m1/__init__.py contains a single line import test.m1.f1 . test/m1/__init__.py包含一行import test.m1.f1

test/m1/f1.py contains a single line import test.m1.f2 as f2 . test/m1/f1.py包含一行import test.m1.f2 as f2

In python 3.7.6, I can do import test.m1 and everything works as expected.在 python 3.7.6 中,我可以执行import test.m1并且一切都按预期工作。 However, in python 3.6.9 when I try this I get the following error:但是,在 python 3.6.9 中,当我尝试此操作时,出现以下错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/scratch/test/m1/__init__.py", line 2, in <module>
    import test.m1.f1
  File "/home/scratch/test/m1/f1.py", line 1, in <module>
    import test.m1.f2 as f2
AttributeError: module 'test' has no attribute 'm1'

This seems strange, because it does not error on the import test.m1.f1 , which is the first thing it encounters.这看起来很奇怪,因为它不会在import test.m1.f1上出错,这是它遇到的第一件事。 It errors on a subsequent import test.m1.f2 as f2 statement, claiming that test has no m1 submodule.它在随后的import test.m1.f2 as f2语句中出错,声称test没有m1子模块。

import test.m1.f2 as f2 tries to access the m1 attribute of the test module object, as part of the process of finding the object to bind to f2 . import test.m1.f2 as f2尝试访问test模块 object 的m1属性,作为查找 object 以绑定到f2的过程的一部分。 The m1 attribute won't be set until the test.m1 subpackage finishes initializing, which won't happen until the __init__.py for test.m1 finishes executing.在 test.m1 子包完成初始化之前不会设置m1属性,直到test.m1__init__.py完成执行test.m1发生。

On Python 3.7 and up , if the attribute lookup fails, the import falls back to a sys.modules['test.m1.f2'] lookup to find test.m1.f2 .在 Python 3.7 及更高版本上,如果属性查找失败,导入将退回到sys.modules['test.m1.f2']查找以查找test.m1.f2 This fallback does not exist on 3.6, causing the observed discrepancy.这种回退在 3.6 上不存在,导致观察到的差异。

A similar fallback also exists for circular from imports on Python 3.5 and up, though from. import f2 Python 3.5 及更高版本上from循环导入也存在类似的回退,尽管from. import f2 from. import f2 or from test.m1 import f2 wouldn't need the fallback. from. import f2from test.m1 import f2不需要后备。 The from import retrieves test.m1 straight from sys.modules , so it only looks for the f2 attribute, and that attribute is present. from import 直接从sys.modules检索test.m1 ,因此它只查找f2属性,并且该属性存在。

This is not the answer explaining the how, but it explains how you can avoid the error.这不是解释如何的答案,但它解释了如何避免错误。 So useful for the ones wanting to write code that runs under 3.6 or earlier.对于想要编写在 3.6 或更早版本下运行的代码的人来说非常有用。

Replace代替

import test1.m1.f2 as f2

with

from test.m1 import f2

Or as @alaniwi pointed out或者正如@alaniwi 指出的那样

from . import f2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM