`ImportError` from python submodule - python

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")

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

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.

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

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?

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