I'm trying to follow PEP 328, with the following directory structure:
pkg/
__init__.py
components/
core.py
__init__.py
tests/
core_test.py
__init__.py
In core_test.py
I have the following import statement
from ..components.core import GameLoopEvents
However, when I run, I get the following error:
tests$ python core_test.py
Traceback (most recent call last):
File "core_test.py", line 3, in <module>
from ..components.core import GameLoopEvents
ValueError: Attempted relative import in non-package
Searching around I found "relative path not working even with __init__.py" and "Import a module from a relative path" but they didn't help.
Is there anything I'm missing here?
unittest
projects, so I wrote this fairly exhaustive sample project that covers deep nesting of modules, relative and absolute imports (where the work and don't), and relative and absolute referencing from within a package, as well as single, double, and package-level import of classes. Helped clear things right up for me!
no module named myimports.foo
when I run them.
cd
into PyImports
, and run python -m unittest tests.test_abs
, for example.
To elaborate on Ignacio Vazquez-Abrams's answer:
The Python import mechanism works relative to the __name__
of the current file. When you execute a file directly, it doesn't have its usual name, but has "__main__"
as its name instead. So relative imports don't work.
You can, as Igancio suggested, execute it using the -m
option. If you have a part of your package that is meant to be run as a script, you can also use the __package__
attribute to tell that file what name it's supposed to have in the package hierarchy.
See http://www.python.org/dev/peps/pep-0366/ for details.
Yes. You're not using it as a package.
python -m pkg.tests.core_test
__init__.py
s all the way down, and the __package__
-modifying trickery (described below by BrenBarn) needed to allow these imports for executable scripts (e.g. when using a shebang and doing ./my_script.py
at the Unix shell) would all be useful. This whole issue was quite tricky for me to figure out or find concise and understandable documentation on.
pkg
at the point where you call this line from the CLI. Then, it should work as expected. If you are inside pkg
and you call python -m tests.core_test
, it will not work. At least it didn't for me.
__init__.py
files yet you keep getting the ValueError: Attempted relative import in non-package
error. I would pay really good money for someone, somewhere, to finally explain in plain English how all of this works.
It depends on how you want to launch your script.
If you want to launch your UnitTest from the command line in a classic way, that is:
python tests/core_test.py
Then, since in this case 'components' and 'tests' are siblings folders, you can import the relative module either using the insert or the append method of the sys.path module. Something like:
import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents
Otherwise, you can launch your script with the '-m' argument (note that in this case, we are talking about a package, and thus you must not give the '.py' extension), that is:
python -m pkg.tests.core_test
In such a case, you can simply use the relative import as you were doing:
from ..components.core import GameLoopEvents
You can finally mix the two approaches, so that your script will work no matter how it is called. For example:
if __name__ == '__main__':
if __package__ is None:
import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents
else:
from ..components.core import GameLoopEvents
python -m pdb myscript.py
to launch the debugging session.
import pdb; pdb.set_trace()
into the code (inline).
insert
instead of append
? That is, sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
You can use import components.core
directly if you append the current directory to sys.path
:
if __name__ == '__main__' and __package__ is None:
from os import sys, path
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
this will also work
from os import sys
looks like cheating :)
sys.path
-- the parent of the directory the current file is in.
import sys, os.path as path
.
import os; os.sys.path.append(os.path.dirname(os.path.abspath('.')))
. Then a straight import components.core
works for me, importing from the notebook's parent directory as desired.
In core_test.py, do the following:
import sys
sys.path.append('../components')
from core import GameLoopEvents
If your use case is for running tests, and it seams that it is, then you can do the following. Instead of running your test script as python core_test.py
use a testing framework such as pytest
. Then on the command line you can enter
$$ py.test
That will run the tests in your directory. This gets around the issue of __name__
being __main__
that was pointed out by @BrenBarn. Next, put an empty __init__.py
file into your test directory, this will make the test directory part of your package. Then you will be able to do
from ..components.core import GameLoopEvents
However, if you run your test script as a main program then things will fail once again. So just use the test runner. Maybe this also works with other test runners such as nosetests
but i haven't checked it. Hope this helps.
Issue is with your testing method,
you tried python core_test.py
then you will get this error ValueError: Attempted relative import in non-package
Reason: you are testing your packaging from non-package source.
so test your module from package source.
if this is your project structure,
pkg/
__init__.py
components/
core.py
__init__.py
tests/
core_test.py
__init__.py
cd pkg
python -m tests.core_test # dont use .py
or from outside pkg/
python -m pkg.tests.core_test
single .
if you want to import from folder in same directory . for each step back add one more.
hi/
hello.py
how.py
in how.py
from .hi import hello
incase if you want to import how from hello.py
from .. import how
from .. import how
, how do you import a specific class / method from the 'how' file. when I do the equivalent of from ..how import foo
then I get "attempted relative import beyond top-level package"
from .. import how
work but the second statement not? I would have assumed that both statements won't work, if the folder that contains the hi folder does not contain an _ _ init _ _.py file. In other words, if there is only an init file in the hi folder, then the hi folder is the top level package and you cannot address beyond it.
My quick-fix is to add the directory to the path:
import sys
sys.path.insert(0, '../components/')
As Paolo said, we have 2 invocation methods:
1) python -m tests.core_test
2) python tests/core_test.py
One difference between them is sys.path[0] string. Since the interpret will search sys.path when doing import, we can do with tests/core_test.py
:
if __name__ == '__main__':
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from components import core
<other stuff>
And more after this, we can run core_test.py with other methods:
cd tests
python core_test.py
python -m core_test
...
Note, py36 tested only.
Old thread. I found out that adding an __all__= ['submodule', ...]
to the __init__.py file and then using the from <CURRENT_MODULE> import *
in the target works fine.
You can use from pkg.components.core import GameLoopEvents
, for example I use pycharm, the below is my project structure image, I just import from the root package, then it works:
https://i.stack.imgur.com/O8dKL.png
This approach worked for me and is less cluttered than some solutions:
try:
from ..components.core import GameLoopEvents
except 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 3:
try:
from ..components.core import GameLoopEvents
except ( ValueError, ImportError):
from components.core import GameLoopEvents
Try this
import components
from components import *
As you have already marked everything as a module, there's no need to use the relative reference if you launch as python module.
Instead of
from ..components.core import GameLoopEvents
simply
from pkg.components.core import GameLoopEvents
When you run from the parent of pkg, use the following
python -m pkg.tests.core_test
If someone is looking for a workaround, I stumbled upon one. 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 work pretty well. In tests run:
ln -s ../components components
Then just import components like you normally would.
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 path
import sys
if __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
.
python
The 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).
Cause
Python Bug Tracker Issue1510172: Absolute/relative import not working?
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.
This is very confusing, and if you are using IDE like pycharm, it's little more confusing. What worked for me: 1. Make pycharm project settings (if you are running python from a VE or from python directory) 2. There is no wrong the way you defined. sometime it works with from folder1.file1 import class
if it does not work, use import folder1.file1 3. Your environment variable should be correctly mentioned in system or provide it in your command line argument.
I've had similar issues and as a software engineer, I think some of the suggested solutions here are not ideal. If you want relative imports, you should not have try/except and then sometimes do an absolute import. Also, to run a program, you should not have to change sys.path.
Furthermore, the program should always work, independent of your current working directory and independent of how you start it.
Thus, I've created a new, experimental import library: ultraimport It allows file system based imports, no matter how you run your code.
From the original question, you would change your core_test.py to something like
import ultraimport
GameLoopEvents = ultraimport('__dir__/../components/core.py', 'GameLoopEvents')
print(GameLoopEvents)
and it would always find it, no matter how you run your tests.
$ python -m tests.core_test
<class 'core.GameLoopEvents'>
python ./tests/core_test.py
<class 'core.GameLoopEvents'>
I've also put this example into the examples folder in the git repo.
As the library is experimental, I am interested in feedback. It works for me but it not widely tested, yet.
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.
if __name__ == "__main__"
in your file makes a difference to anything related to importing.
Success story sharing
python -m core_test
from within thetests
subdirectory - it has to be from the parent, or you have to add the parent to the path.__package__
to ensure executable script files can relatively import other modules from within the same package. There's no way to relatively import from "the whole system". I'm not even sure why you'd want to do this.__package__
symbol is set to "parent.child" then you'd be able to import "parent.other_child". Perhaps I didn't phrase it so well.script.py
in packagepack.subpack
, then setting it's__package__
topack.subpack
will let you dofrom ..module import something
to import something frompack.module
. Note that, as the documentation says, you still have to have the top-level package on the system path. This is already the way things work for imported modules. The only thing__package__
does is let you use that behavior for directly-executed scripts as well.__package__
in the script which is executed directly but Unfortunately, I get the the following error: "Parent module 'xxx' not loaded, cannot perform relative import"