Message380437
Steps to reproduce:
Create the following three files (or download the attached zip file, which contains these files):
main.py
import foo
from foo import a
from foo import b
print(foo.b.my_function())
foo/a.py
import importlib.util
import sys
# implementation copied from https://github.com/python/cpython/blob/master/Doc/library/importlib.rst#implementing-lazy-imports
def lazy_import(name):
spec = importlib.util.find_spec(name)
loader = importlib.util.LazyLoader(spec.loader)
spec.loader = loader
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
loader.exec_module(module)
return module
b = lazy_import("foo.b")
foo/b.py
def my_function():
return "my_function"
and then run main.py
Expected results
my_function should be printed to the terminal
Actual results
The following traceback is printed to the terminal
Traceback (most recent call last):
File "F:\Documents\lazy_import\main.py", line 6, in <module>
print(foo.b.my_function())
AttributeError: module 'foo' has no attribute 'b'
If you comment out "from foo import a" from main.py, then the traceback doesn't occur and my_function gets printed. Alternatively, if you move "from foo import a" after "from foo import b", then the traceback doesn't occur and my_function gets printed. Adding "foo.b = b" before "print(foo.b.my_function())" will also fix the traceback.
A colleague of mine originally ran into this bug when writing unit tests for lazily imported code, since mock.patch("foo.b.my_function") triggers the same AttributeError. I've reproduced this on Windows using both Python 3.8.3 and Python 3.9.0, and my colleague was using Python 3.8.3 on Mac. |
|
Date |
User |
Action |
Args |
2020-11-05 22:14:23 | KevKeating | set | recipients:
+ KevKeating |
2020-11-05 22:14:23 | KevKeating | set | messageid: <1604614463.81.0.853919807892.issue42273@roundup.psfhosted.org> |
2020-11-05 22:14:23 | KevKeating | link | issue42273 messages |
2020-11-05 22:14:23 | KevKeating | create | |
|