Import directory errors with Python 3.5 and above - python

I want to import modules from folder and subfolder with Python 3.6.
Currently I have a structure like this.
└── project
│ main.py
├── package1
│ ├── __init__.py
│ └── module1.py
└── package2
├── __init__.py
├── module2.py
When I import module1 and module2, I have no problem with that.
Within main.py having this scripts to import both modules.
from package1 import module1
from package2 import module2
It works fine!
But I want to move package2 with module2 into a subfolder under package1 as shown below:
└── project
│ main.py
└── package1
├── __init__.py
├── module1.py
└── subpackage1
├── __init__.py
├── module2.py
And want to call module2 from main.py. Having tried following path and scripts does not fix my problem I get import error, it can not find the path.
Within main.py having this scripts to import both modules.
from package1.subpackage1 import module2
or
from package1.subpackage1.module2 import Class_in_module2
or
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
from package1.subpackage1 import module2
It does not work. Path can not be found!
Any help appreciate!

Since the from keyword accepts an hierarchy of folders and import the specific method from the file, this should work.
from MainFolder.SubFolder.SomeDotPy import foo,bar,somevalue

Related

ImportError for folders as modules: "attempted relative import with no known parent package"

My folder structure looks like below
.
└── myfolder/
└── mock/
├── __init__.py
└── main.py
└── common/
├── __init__.py
└── db.py
└── routers
└── myroute.py
└── __init__.py
My main.py
from fastapi import FastAPI
from ..common.db import create_db_and_tables
from ..common.routers import myroute
app = FastAPI()
app.include_router(myroute.router)
Now from inside of mock if I run the main.py, I am getting python ImportError: attempted relative import with no known parent package .
I am not sure whats I am missing here

python 3.9 Package Relative Imports not working

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.

how to import a submodule into my test module?

I have a project structured as follows:
.
└── MYAPP/
├── data/ # contains data files i.e: html/json/db files.
├── src/
│ └── myapp/
│ ├── __init__.py
│ ├── core.py
│ └── utils.py
└── tests/
├── conftest.py
├── test_core.py
└── test_utils.py # contains ClassA and ClassB
conftest.py contains the following:
import pytest
from src.myapp.utils import ClassA, ClassB
as you can see in the contents of conftest.py, I am importing the required classes using an absolute import.
By chance while reading through Flask's source code on github, I saw that they were using a similar project structure:
.
└── flask/
├── src/
│ └── flask
└── tests
and in test files were not using absolute imports, for example in the conftest.py file they had the following:
import pytest
from _pytest import monkeypatch
import flask
from flask import Flask as _Flask
My question is, How did flask achieve to import its module into test by just using import flask or from flask import Flask as _Flask. when I attempt to do that (import myapp), I end up with ModuleNotFoundError: No module named 'myapp'

What is a correct way to chain import submodules?

Let's say I have a project with following structure:
├── modules
│   ├── modulea.py
│   └── moduleb.py
└── program.py
program.py is the main executable, which imports module a like so
from modules import modulea
in modulea I would like to import something from moduleb. Now, logically, I should be doing import moduleb as it is in the same directory. But that would yield ModuleNotFoundError: No module named 'moduleb'
So in order for this chain import to work, I either have to do from modules import moduleb. which angers IDEs as there is no "modules" directory around or from . import moduleb which angers pylint.
While both of the methods above work, they feel confusing and unpythonic as one is assuming that imports are going to happen from one level above and one is using relative imports where it doesn't seem necessary.
Is there a way to handle this with more grace?
Thank you.
You can make modules a python package by creating a __init__.py file in it.
├── modules
│ ├── __init__.py
| ├── modulea.py
│ └── moduleb.py
└── program.py
Then use from modules.moduleb import some_object in modulea.

Error when import a function from a py file in other directory

I have a directory like
.
└── my_project
├── API
│ ├── __init__.py
│ └── admin.py
└── my_project
├── __init__.py
└── module1_file.py
Inside API/admin.py, I want to import func1 from my_project/module1_file.py. I do like this:
import sys
sys.path.insert(0, './myproject/myproject/')
from module1_file import func1
It throws me this error
from module1_file import func1
ModuleNotFoundError: No module named 'module1_file'
Can anyone please show me how to solve this? Thanks.

Categories