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
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.
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'
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.
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.