Reputation: 88118
Given a directory structure like this
main/
common/
foo.py
A/
src/
bar.py
How can I use Python's relative imports to import foo
from bar
? I've got a working solution by adding it to the path, but this is ugly. Is there a way to simply do with a single import
in Python 2.7?
This is a more complex version of this question:
Importing modules from parent folder
Upvotes: 56
Views: 82233
Reputation: 23
If you are working with framework that uses OPSEC practices to limit the top-level-project of scripts but you need to import a local library from another place without copy-paste the same library for every script... (the reason cause im here) You can bypass the problem with a simbolic link to the folder that contains the code.
4 your example its like:
cd path2/A
ln -s path2/main/common common
then you can import in bar.py with
from A.common.foo import class
But if you do this instead of creating __init__.py's when its required then you have my intense dissaproval.
Upvotes: 0
Reputation: 150
In order to use relative imports, you have to have a package. In this example I think 'main' folder is the best candidate to be the top level package. Make a __init__.py
inside 'main' folder and put the following code inside it to make it the top level folder in package:
__package__ = ''
Now you can use relative imports:
from ...common import foo
Upvotes: 0
Reputation: 229281
The correct relative import would be this:
from ...common import foo
However, relative imports are only meant to work within one package. If main
is a package, then you can use relative imports here. If main
is not a package, you cannot.
Thus, if you're running a script in /main/
and doing something like import A.src.bar
, then that relative import will fail with "Attempted relative import beyond toplevel package". This is because the relative import is trying to import something outside of the toplevel package A
.
However, if you're running a script in /
and doing something like import main.A.src.bar
, then that relative import will succeed because main
is now a package. In that case, the following two would be equivalent:
from ...common import foo
from main.common import foo
To answer your comment: the meaning of the .
doesn't change depending on where the script was run from, it changes depending on what the package structure is.
Upvotes: 60