[issue18145] Strange behavior when importing internal modules in the __init__.py of a submodule
New submission from Antoine Pietri: I just found a very strange bug today, and it took me like two hours to figure out the problem. We first create a package package, which contains an __init__.py, which makes an absolute import of package/foo.py (import package.foo), which makes an absolute import of package/bar.py (import package.bar). Everything works fine as expected, the modules are imported correctly in the __init__.py and we can use them. Now, if we move everything in a subpackage, the behavior is complete nonsense. We then have package/subpackage/{foo,bar,__init__}.py and an empty package/__init__.py. We can import package.subpackage.foo and use it, but when we import package.subpackage.bar, the import statement works as expected but we CAN'T use the imported package: import package.subpackage.bar # works fine dir(package.subpackage.bar) # WAT AttributeError: 'module' object has no attribute 'subpackage' You can find a tarball attached to this bug report that contains the working case and the failing case: package1 ├── bar.py ├── foo.py └── __init__.py package2 └── subpackage ├── bar.py ├── foo.py └── __init__.py $ python3 import package1.foo __init__: importing package1.foo foo.py: importing package1.bar foo.py: package1.bar.__name__: package1.bar __init__: package1.foo.__name__: package1.foo import package2.subpackage.foo __init__: importing package2.subpackage.foo foo.py: importing package2.subpackage.bar Traceback (most recent call last): File stdin, line 1, in module File ./package2/subpackage/__init__.py, line 2, in module import package2.subpackage.foo File ./package2/subpackage/foo.py, line 3, in module print('foo.py: package2.subpackage.bar.__name__:', package2.subpackage.bar.__name__) AttributeError: 'module' object has no attribute 'subpackage' tl;dr: you can use only relative imports to refer to modules of a package inside a module imported by the __init__.py of this package except if the package is not a subpackage. Else, the package will be successfully imported but trying to use it will lead to a weird AttributeError. (Wat.) -- components: Interpreter Core files: lolpython.tar.xz messages: 190688 nosy: seirl priority: normal severity: normal status: open title: Strange behavior when importing internal modules in the __init__.py of a submodule type: behavior versions: Python 3.3 Added file: http://bugs.python.org/file30478/lolpython.tar.xz ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18145 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18145] Strange behavior when importing internal modules in the __init__.py of a submodule
Changes by Brett Cannon br...@python.org: -- versions: +Python 2.7, Python 3.4 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18145 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18145] Strange behavior when importing internal modules in the __init__.py of a submodule
Brett Cannon added the comment: It's because you have a nested circular import. When you import package2.subpackage from within package2.subpackage you're in package2 importing package2 and also in package2.subpackage importing package2.subpackage. You can solve your problem by doing either ``from package2.subpackage import foo`` for ``from . import foo`` as that lets package2.subpackage be imported entirely on its own before attempting package2.subpackage.foo and thus letting the circular loop unroll and have the right attributes set since the attributes of a module for a package are set after the import completes. Might be annoying, but tweaking this would probably break code if changed as it's very old semantics to set the attribute of a module on a package after other imports complete. This is also not a problem as long as you don't do this in an __init__ (e.g. importing package2.subpackage.bar from package2.subpackage.foo is not a problem). -- nosy: +brett.cannon resolution: - wont fix status: open - closed ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18145 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18145] Strange behavior when importing internal modules in the __init__.py of a submodule
Antoine Pietri added the comment: Okay, maybe my message was unclear. I figured out on my own how to work around this issue (for instance using relative imports), the main problem for me is that this issue is very difficult to debug. The import statement should at least fail with a more explicit error, imho. -- resolution: wont fix - status: closed - open ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18145 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18145] Strange behavior when importing internal modules in the __init__.py of a submodule
Brett Cannon added the comment: It can't. The AttributeError is in the executing module code, not import itself so there is no reasonable way to tell that the failure was because of a circular loop in the import and not simply because you tried to get at an attribute that doesn't exist for some other reason. -- resolution: - invalid status: open - closed ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue18145 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com