Not a python developer and I am clearly missing something fundamental here. Using Python 3.10.7 and i am getting an error:
from ..class_one import ClassOne
ImportError: attempted relative import beyond top-level package
when attempting to execute python run_me.py
script in the example below
I have the following structure with following import statements
\Project
\data_processor
data_process.py
from ..class_one import ClassOne <--getting an error here
run_me.py
from data_processor.data_process import DataProcess
class_one.py
interesting that when i type a line from ..class_one import ClassOne
in data_process.py
my IDE thinks its completely legit and intellisence works, suggesting that i import ClassOne
.
Most of the solutions imply Python earlier than v3.3 (changed the way packages are handled), which isn't the case here.
CodePudding user response:
Python does not allow relative imports beyond the top-level package. This is why you are seeing the ImportError: attempted relative import beyond top-level package error...
Try to use absolute import, like this:
from Project.class_one import ClassOne
You can also move the class_one module to a package within the current project, you can create a new package and move the class_one module to it. Then, you can use a relative import to import the ClassOne module:
\Project
\data_processor
data_process.py
from my_package.class_one import ClassOne
run_me.py
from data_processor.data_process import DataProcess
\my_package
class_one.py
Finally, it's not recommended (complexity, cause confusion and difficulty to read the code) but I think you can try to use a 'sys.path' to add the parent directory to the Python path. I think it will allow you to use a relative import:
import sys
sys.path.insert(0, '..')
from class_one import ClassOne
CodePudding user response:
Why you get that error?
Remember relative imports are resolved using __package__
variable(I'm talking about ..class_one
). Add a simple print statement in your data_process.py
to see the value of this variable:
print(__package__)
You're in Project
folder and you run python run_me.py
, so this variable must be: 'data_processor'
. So you can't go beyond "one" level up. (It follows the dots as we see next).
When you can go one level up?
In run_me.py
change your import statement from:
from data_processor.data_process import DataProcess
to
from Project.data_processor.data_process import DataProcess
Before running your script, we need to tell Python where to find Project
folder. It doesn't know right now! We are in Project
directory and there is no Project
directory in where we are. So just add it to the sys.path
in run_me.py
:
import sys
sys.path.insert(0, PATH TO PARENT OF Project DIRECTORY)
Now run your command -> python run_me.py
. Every thing works fine.
Did you notice the value of __package__
? It's now 'Project.data_processor'
. We went one level down, so we can go one level up .( As I said, it follows the dots.)
That was the reason. But what you can do now?
I think the most simple solution is to just stick with absolute imports. If you know in which directory you are and check the records in
sys.path
, you won't get into problems.You can manually hack
__package__
which I do not recommend. To do so, add:
__package__ = "Project.data_processor"
at the top in your data_process.py
file. Then change your directory to the parent, and tun your script like:
python -m Project.run_me