Python 3: importing module names consisting of similar components. AttributeError - python

I have the following folder structure:
├── aaa
│   ├── __init__.py
│   ├── ttt
│   │   ├── aaa.py
│   │   └── __init__.py
│   └── ttt.py
├── __init__.py
├── t.py
└── ttt.py
The main script t.py:
import sys
sys.path = ['.']
import ttt
import aaa.ttt
import aaa.ttt.aaa
print(ttt.get_name())
print(aaa.ttt.get_name2())
print(aaa.ttt.aaa.get_name3())
The imported scripts:
./ttt.py
def get_name():
return "ttt"
./aaa/ttt.py
def get_name2():
return "aaa/ttt"
./aaa/ttt/aaa/ttt.py
def get_name3():
return "aaa/ttt/aaa"
Now running the main script:
$ python -B t.py
ttt
Traceback (most recent call last):
File "t.py", line 10, in <module>
print(aaa.ttt.get_name2())
AttributeError: module 'aaa.ttt' has no attribute 'get_name2'
What is the problem here? I am using Python 3.6.1.
Edit
As commented by #AChampion, a problem is that I have
aaa/ttt.py and aaa/ttt/__init__.py. However, if I remove the latter I get a ModuleNotFoundError on import aaa.ttt.aaa:
$ python -B t.py
Traceback (most recent call last):
File "t.py", line 7, in <module>
import aaa.ttt.aaa
ModuleNotFoundError: No module named 'aaa.ttt.aaa'; 'aaa.ttt' is not a package
Does this mean that if you have a package aaa.bbb in Python, then you cannot have any modules in package aaa named bbb? This smells bad design, so I guess I must be missing something here?

Related

ModuleNotFoundError: No module named 'commandlineproject'

I know there are a lot of questions like this but still nothing makes sense to me.
└── commandlineproject
├── commands
│ ├── add.py
├ ├── update.py
├ ├──__init__.py
├── __init__.py
├── main.py
├──myscript.py
This is my code in main.py
from commandlineproject.commands.add import add
from commandlineproject.commands.update import update
from commandlineproject.myscript import parser_args
import sys
And this is a Command line application. I dont know if this relevant or not but this is code which i want to work
update(vars(parser_args(sys.argv[1:])))
And whenever run it from terminal this is the error i get
Traceback (most recent call last):
File "commandlineproject\main.py", line 1, in <module>
from commandlineproject.commands.add import add
ModuleNotFoundError: No module named 'commandlineproject'

Why is absolute import failing with Python 2, but succeeding with Python3?

While fiddling with Python import system, I noticed this form of absolute import works well with Python 3.6.8, but throws ImportError with Python 2.7.17. The package structure is as follows:
├── main8.py
├── pkg_a
│   ├── __init__.py
│   ├── mod7.py
│   ├── pkg_c
│   │   ├── __init__.py
│   │   ├── mod2.py
main8.py
import pkg_a.mod7
pkg_a/mod7.py
import pkg_a.pkg_c.mod2
pkg_a/pkg_c/mod2.py
print('Imported pkg_a.pkg_c.mod2')
If I execute main8.py with Python3, pkg_a.pkg_c.mod2 gets imported successfully.
$ python3 main8.py
Imported pkg_a.pkg_c.mod2
However, If I execute main8.py with Python2, it throws an ImportError.
$ python2 main8.py
Traceback (most recent call last):
File "main8.py", line 1, in <module>
import pkg_a.mod7
File "pkg_a/mod7.py", line 1, in <module>
import pkg_a.pkg_c.mod2
ImportError: No module named pkg_c.mod2
Adding from __future__ import absolute_import directive at the top of main8.py and pkg_a/mod7.py didn't help. Can anyone please explain why Python2 import is behaving like this?
For Python2 you need to have a __init__.py next to main8.py to make a package:
.
├── __init__.py
├── main8.py
└── pkg_a
├── __init__.py
├── __init__.pyc
├── mod7.py
├── mod7.pyc
└── pkg_c
├── __init__.py
├── __init__.pyc
├── mod2.py
└── mod2.pyc
2 directories, 10 files
Running:
>> /usr/bin/python2.7 ./main8.py
Imported pkg_a.pkg_c.mod2
>> python3 ./main8.py
Imported pkg_a.pkg_c.mod2

`ImportError` from python submodule

I have the following structure for my Python modules:
.
├── a
│   ├── __init__.py
│   ├── aa.py
│   └── b
│   ├── __init__.py
│   └── bb.py
└── root.py
Contents of aa.py
from b.bb import hello_bb
def hello_aa():
hello_bb()
print("hello from aa.py")
Contents of bb.py
def hello_bb():
print("hello from bb.py")
Contents of root.py
from a.aa import hello_aa
hello_aa()
With Python 3.5.1, executing python root.py gives the following error:
Traceback (most recent call last):
File "root.py", line 1, in <module>
from a.aa import hello_aa
File ".../a/aa.py", line 1, in <module>
from b.bb import hello_bb
ImportError: No module named 'b'
Both the __init__.py are empty.
Anything else I am missing to make this work?
Use relative import inside a package (see PEP 328)
aa.py
from .b.bb import hello_bb
root.py
from .a.aa import hello_aa
In the aa.py file you must import hello_bb like so:
from .b.bb import hello_bb
def hello_aa():
hello_bb()
print("hello from aa.py")

Import a submodule of a package while the pacakge is being loaded

I am importing a package foo1.foo2, whose __init__.py is importing a submodule foo1.foo2.foo3.bar1, which is a file. If I try to import foo1.foo2.foo3.bar2 inside that file I get the following error:
AttributeError: module 'foo1' has no attribute 'foo2'
Given that the use of relative imports is discouraged, how can I solve this issue without using relative imports?
Here is the package structure and file contents that I have:
/
├── foo1
│   ├── __init__.py:
│   └── foo2
│   ├── __init__.py: "import foo1.foo2.foo3.bar1"
│   └── foo3
│   ├── __init__.py
│   ├── bar1.py: "import foo1.foo2.foo3.bar2 as bar2"
│   └── bar2.py:
└── main.py: "import foo1.foo2"
Running python main.py generates the following error:
Traceback (most recent call last):
File "main.py", line 1, in <module>
import foo1.foo2
File "/foo1/foo2/__init__.py", line 1, in <module>
import foo1.foo2.foo3.bar1
File "/foo1/foo2/foo3/bar1.py", line 1, in <module>
import foo1.foo2.foo3.bar2 as bar2
AttributeError: module 'foo1' has no attribute 'foo2
I'm using Python 3.6.0 :: Anaconda 4.3.1.
Thanks!
Change import foo1.foo2.foo3.bar2 as bar2 into from foo1.foo2.foo3 import bar2.
Then it works.

Import module from sibling package with absolute import

How does one use absolute imports from a module of a sibling package?
Package file structure:
.
├── a
│   ├── __init__.py
│   └── modulea.py
├── b
│   ├── __init__.py
│   ├── moduleb.py
├── __init__.py
└── test.py
Files test.py and a/modulea.py:
from b.moduleb import f
if __name__ == '__main__':
f()
File b/moduleb.py:
def f():
print('hello')
This works:
% python test.py
hello
This does not:
% python a/modulea.py
Traceback (most recent call last):
File "a/modulea.py", line 1, in <module>
from b.moduleb import f
ImportError: No module named 'b'
As far as I can tell from the documentation it should work: http://docs.python.org/3.3/tutorial/modules.html#intra-package-references. Am I missing something?
You need an __init__.py in whatever . is.
Use python -ma.modulea.
Running python a/modulea.py adds a directory to sys.path instead of the parent (.).
Don't run scripts from inside Python packages directly. See Traps for the Unwary.

Categories