python 3.9 Package Relative Imports not working - python

I am setting up a sample python package using the "Package Relative Imports" syntax, referring to this document. And it is not working, the Relative Imports in b.py ran into problems. Here are my file structure (all __init.py__ are empty)
lib/
dir1/
__init.py__
a.py
dir2/
__init.py__
b.py
__init.py__
c.py
File a.py
def a_foo(a, b):
return a + b
File b.py
from ..dir1.a import a_foo
def b_bar():
return a_foo(1,2)
File c.py
from dir2.b import b_bar
print(b_bar())
I ran c.py and got the following error
PS D:\tmp\py> python c.py
Traceback (most recent call last):
File "D:\tmp\py\c.py", line 1, in <module>
from dir2.b import b_bar
File "D:\tmp\py\dir2\b.py", line 1, in <module>
from ..dir1.a import a_foo
ImportError: attempted relative import beyond top-level package
I think I structured everything according to the document. Not sure why the relative import is not working. I have a Python 3.9.7 running in Windows 10.

I think your from dir2.b is being interpreted as an absolute import, not relative. The docs you refer to say:
Try:
from .dir2.b import b_bar
Note the preceding period. It means look in the current directory for "dir2"
Then call it using
python -c "import lib.c"

To get a simple idea Lets look at the directory tree again
lib
├── c.py
├── dir1
│   ├── a.py
│   └── __init__.py
├── dir2
│   ├── b.py
│   └── __init__.py
└── __init__.py
Important things
In this tree, the top most __init__.py file is in the root directory.
All other subfolders with python scripts are included __init__.py
OK, Here comes the point. When you are trying to do relative import with .. it tries to import from lib.dir1.a, But there is no __init__.py at the same level with lib folder. That's why you get ImportError: attempted relative import beyond top-level package error. Because of python package importer doesn't identify lib folder as the top level package.
When you are trying to relative import with . , you checks dir2.dir1.a , which doesn't exit. Sow it will give you ModuleNotFoundError: No module named 'dir2.dir1' error
OK lets check whether it's true or not. lets add new folder dir3 within dir1 and d.py,e.py and __init__.py inside it
Here is the NEW directory tree
lib
├── c.py
├── dir1
│   ├── a.py
│   ├── dir3
│   │   ├── d.py
│   │   ├── e.py
│   │   └── __init__.py
│   └── __init__.py
├── dir2
│   ├── b.py
│   └── __init__.py
└── __init__.py
And here are the NEW file contents
a.py
def a_foo(a, b):
return a + b
b.py
from dir1.a import a_foo
def b_bar():
return a_foo(1,2)
e.py
def e_foo(a, b):
return a + b
d.py
from ..a import a_foo
from .e import e_foo
def d_bar():
return a_foo(1,2)
def d_foo():
return e_foo(1,2)
.. , Which tries to import from dir1.a, which exists and also which is accessible.
. , Which tries to import from dir3.e, which exists and also which is accessible.
c.py
from dir2.b import b_bar
from dir1.dir3.d import d_bar,d_foo
print("b_bar:", b_bar())
print("d_bar:", d_bar())
print("d_foo:", d_foo())
Now lets run c.py. The result is
b_bar: 3
d_bar: 3
d_foo: 3
Which indicates our relative import has been successful inside d.py.
OK then. I think this will solve your problem. We can use relative import in files which are in depth from the root-package. But when they are too close (within one or two levels), it's impossible.
Actually we can use . to import from python scripts in same level but not when the script is in the top most directory.

Related

How to import method from one package to another for the directory structure below?

Below is the directory structure where I am having trouble importing modules.
.
├── A
│   └── a.py
└── B
└── C
└── b.py
Let's say, there's a method foo() in B/C/b.py which is to be imported into A/a.py.
However, when I try importing foo() as shown below -
# A/a.py
from B.C import foo
I get an error saying -
unable to import 'B.C'.
An alternative way that I tried was using relative imports like this -
# A/a.py
from ..B.C import foo
But again, I get an error saying
Attempted relative import beyond top-level package.
How exactly should I import foo() from B/C/b.py into A/a.py?
You need to structure your project as a package.
By adding __init__.py file as specified here, you are specifying a top-level package, therefore you will be able to import B/C/b.py with the command:
from src.B.C import b
src
├── __init__.py
├── A
│ ├── a.py
│ └── __init__.py
└── B
├── __init__.py
└── C
├── __init__.py
└── b.py

Python ModuleNotFoundError: No module named '<directory>''

I want to import a file from subdir and I get an error like that:
ModuleNotFoundError: No module named 'special'
│
├── constants.py
├── crawler.py
├── case.py ===================>>>> I working on this file
├── special
├── __init__.py
└── wantToImport.py =================>>>I want to import this file
My case.py like that:
from special.wantToImport import ImportClass
And my wantToImport.py file like that:
class ImportClass:
def mydefination(self):
#Some codes here
I want to use mydefinitioon function on my case.py file But I cannot import this file.
Why Im getting this error?
How can I solve this?
You should tell Python that your module's path is inside the current directory (using a .):
from .special.wantToImport import ImportClass
Try creating a __init__.py file in the directory where you are working and use it to refer your module.
│
root
├── constants.py
├── crawler.py
├── case.py ===================>>>> I working on this file
├── __init__.py
├── special
├── __init__.py
└── wantToImport.py =================>>>I want to import this file
inport it using
from root.special.wantToImport import ImportClass

Import own files in python

Imagine a main.py.
I have the following structure
├── main.py
├── moduleX
│   ├── setup.py
│   ├── submoduleA
│   │   └── fileA.py
│   │   └── fileB.py
│   ├── submoduleC
│   │   └── fileC.py
Main calls moduleX.setup and setup needs to call functions from submodules A and B.
However moduleX.setup is unable to find the submodules and I don't know how to import them
So it goes like this:
in main.py
import moduleX.setup
in setup.py
from submoduleA import fileA
from submoduleA import fileB
import submoduleC
and all submodules and files are not found.
All subfolders have empty init.py files. I am not sure how to fill them, seems like a recursive problem.
I tried adding moduleX to sys.path
I tried prpending moduleX everywhere
I tried using .. and .
I don't know what I am doing wrong.
Python always uses the relative path to the file you are executing.
from moduleX.submoduleA import fileA
from moduleX.submoduleA import fileB
import moduleX.submoduleC
should work

Absolute import results in ModuleNotFoundError

Python 3.6
I've written some components and I'm trying to import one of them in the other.
Below is what my project structure looks like:
.
└── components
├── __init__.py
   ├── extract
│   └── python3
| ├── __init__.py
│   └── extract.py
   └── transform
   └── python3
├── __init__.py
   └── preprocess.py
extract.py
from components.transform.python3.preprocess import my_function
if __name__ == '__main__':
my_function()
preprocess.py
def my_function():
print("Found me")
When I run python components/extract/python3/extract.py
I see the following error:
ModuleNotFoundError: No module named 'components'
I've added an empty __init__.py file to the directories that contain modules as well as the top level package directory.
Ok, imports require the top level package to be available in Python PATH (sys.path).
So to make it work, you should:
cd to the directory containing components
add . to the Python PATH:
export PYTHONPATH='.'
launch your script:
python components/extract/python3/extract.py
On my system, it successfully displays:
Found me

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