This approach worked for me and is less cluttered than some solutions:
try:from ..components.core import GameLoopEventsexcept ValueError:from components.core import GameLoopEvents
The parent directory is in my PYTHONPATH, and there are __init__.py
files in the parent directory and this directory.
The above always worked in Python 2, but Python 3 sometimes hit an ImportError or ModuleNotFoundError (the latter is new in Python 3.6 and a subclass of ImportError), so the following tweak works for me in both Python 2 and Python 3:
try:from ..components.core import GameLoopEventsexcept ( ValueError, ImportError):from components.core import GameLoopEvents
Try this
import componentsfrom components import *
python <main module>.py
does not work with relative importThe problem is relative import does not work when you run a __main__
module from the command line
python <main_module>.py
It is clearly stated in PEP 338.
The release of 2.5b1 showed a surprising (although obvious in retrospect) interaction between this PEP and PEP 328 - explicit relative imports don't work from a main module. This is due to the fact that relative imports rely on
__name__
to determine the current module's position in the package hierarchy. In a main module, the value of__name__
is always'__main__'
, so explicit relative imports will always fail (as they only work for a module inside a package).
The issue isn't actually unique to the -m switch. The problem is that relative imports are based on
__name__
, and in the main module,__name__
always has the value__main__
. Hence, relative imports currently can't work properly from the main module of an application, because the main module doesn't know where it really fits in the Python module namespace (this is at least fixable in theory for the main modules executed through the -m switch, but directly executed files and the interactive interpreter are completely out of luck).
To understand further, see Relative imports in Python 3 for the detailed explanation and how to get it over.
For me only this worked: I had to explicitly set the value of package to the parent directory, and add the parent directory to sys.path
from os import pathimport sysif __package__ is None:sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )__package__= "myparent"from .subdir import something # the . can now be resolved
I can now directly run my script with python myscript.py
.
If your project structure would look like this:
project|| --- module1| || file1.py||-----module2| || file2.py
and you are going import file1.py from within file2.py,you can do this in file2.py:
import syssys.path.append('.')import file2
I still don't know why and how, but it worked for me.
Here is a workaround. Here's a bit of context. I wanted to test out one of the methods I've in a file. When I run it from within
if __name__ == "__main__":
it always complained of the relative imports. I tried to apply the above solutions, but failed to work, since there were many nested files, each with multiple imports.
Here's what I did. I just created a launcher, an external program that would import necessary methods and call them. Though, not a great solution, it works.
Here's one way which will piss off everyone, but it works pretty well. In tests, run:
ln -s ../components components
Then just import components like you normally would.
This is very confusing and if you are using IDE like PyCharm, it's little more confusing.
What worked for me:
Make PyCharm project settings (if you are running Python from a venv or from Python directory)
There is nothing wrong with the way you defined. Sometime it works with:
from folder1.file1 import class
If it does not work, use:
import folder1.file1
Your environment variable should be correctly mentioned in system or provide it in your command-line argument.
Because your code contains if __name__ == "__main__"
, which doesn't be imported as a package, you'd better use sys.path.append()
to solve the problem.