Basically I'm asking the same question as this guy: How to do relative imports in Python?
But no one gave him a correct answer. Given that you are inside a subfolder and you want to go up a directory and then into ANOTHER subfolder, doing what they suggested does not work (as the OP pointed out in his comments to their answers).
I know that you can do this by using sys.path, but I would prefer a cleaner method.
Example:
App
__init__.py
Package_A
--__init__.py
--Module_A.py
Package_B
--__init__.py
--Module_B.py
How would I import Module_A into Module_B?
main.py
setup.py
app/ ->
__init__.py
package_a/ ->
__init__.py
module_a.py
package_b/ ->
__init__.py
module_b.py
You run python main.py.
main.py does: import app.package_a.module_a
module_a.py does import app.package_b.module_b
Alternatively 2 or 3 could use: from app.package_a import module_a
That will work as long as you have app in your PYTHONPATH. main.py could be anywhere then.
So you write a setup.py to copy (install) the whole app package and subpackages to the target system's python folders, and main.py to target system's script folders.
If I'm reading correctly, in Python 2.5 or higher:
from ..Module_B import Module_B
I thought I was well-versed in Python but I had no idea that was possible in version 2.5.
If you are then importing Module_B in to App, you would
Module_B.py:
import ModuleA
App.py (which also imports ModuleA which is now by default in your Pythonpath)
import Module_B.Module_B
Another alternative, is to update __init__.py (the one in Module_A/App folder) to:
import os
import sys
sys.path.extend('%s../' % os.getcwd())
import ModuleA
Another alternative, is to add your folder to the PYTHONPATH environment var.
Related
I have this package I designed which have the following structure,
General/
__init__.py
Vector/
__init__.py
module_1.py
module_A.py
In module_A there is a just a function prints a string.
In module_1 there is,
from ...General import module_A
module_A.function()
Then I create a separate python file First.py which only has the line import General.Vector.module_1.
I put this file in to the parent directory of General and locate cmd to the parent directory and run python First.py
Then I get the error ValueError: attempted relative import beyond top-level package
But if I change module_1 to
from .. import module_A
module_A.function()
Then this works.
I searched for a solution and from this post, I got a good understanding about relative imports. Then it was pointed out to me that if I add my package to sys.path then python First.py would work regardless of where the First.py is located.
So I tried to add my package to sys.path as this post suggests.
I changed my First.py to
import sys
sys.path.insert(0,'/path/to/General')
import General.Vector.module_1
But that didn't work.
1 I like to know the reason for this two different behaviours for module_1's changes.
2 I like to know how to add my package to sys.path.
I'll shorten the notation. I have
PYTHONPATH=/path1/dir1:/path2/dir2
Structures:
/path1/dir1/
README
muggle.py
...
utils/
/path2/dir2/
__init__.py
utils/
__init__.py
pkg2/
__init__.py
mod2.py
dir1 has a module utils, but is not, itself a package: no __init__.py
dir2 has a module utils, and does have __init__.py
My boiler-plate code (before dir1 was part of the environment) has imports from dir2 of the form
from utils.pkg2.mod2 import func2
The problem comes in that I'm now adapting this code to call functions that import from utils in dir1; I cannot alter that part of the environment.
What can I do to make my code go for the dir2/utils module? Unfortunately, this also needs to be adaptable to Python 2.6.6 and later.
I have search existing questions on SO and elsewhere; all the answers I've found depend on some package "handle" that I do not have.
This import statement is incorrect:
from utils.pkg2.mod2 import func2
If it has ever worked correctly, that was relying on resolving with the current working directory, implicit relative imports in Python 2.x, or a manually munged PYTHONPATH / sys.path.
This is the type of import for which PEP8 said:
Implicit relative imports should never be used and have been removed in Python 3.
So what to do instead? sys.path should be augmented with top-level directories, not intra-package directories, i.e.:
PYTHONPATH=/path1/dir1:/path2
And change imports like this:
from dir2.utils.pkg2.mod2 import func2
Now the sub-package dir2.utils is namespaced from the top-level package utils.
I want to use relative import in Python 3.
My project:
main_folder
- __init__.py
- run.py
- tools.py
I want to have in run.py (MyClass declared in __init__.py):
from . import MyClass
And in run.py:
from .tools import my_func
An ImportError is raise.
Alternatively, with absolute import, debugging in PyCharm does not work and the library takes from installed packages, not my directory.
I know one way, but it is terrible:
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
How to use this import in my project?
When you use PyCharm, it automatically makes the current module main, so relative statements like from . import <module> will not work. read more here.
to fix your problem, put the __init__.py and tools.py files in a sub-directory
main_directory/
run.py
sub_directory/
__init__.py
tools.py
in your run.py file, write the following as your import statements
from sub_directory import tools
from sub_directory.__init__ import MyClass
Edit: as #9000 mentioned, you can write from sub_directory import MyClass and achieve the same thing.
How do I link the util.py file to the script.py file?
App
Module
__init__.py
util.py
Main
__init__.py
Dir1
script.py
__init__.py
Dir2
script.py
__init__.py
Take this directory layout of my app. It's a bit more complex for requirement reasons to keep the scripts easily separated while sharing the same module across each script. However, it's difficult to find the correct way to import that module to each script due to directory hierarchy.
Environment
Python 2.7, Windows 10, 64Bit
Just add the root directory to the PYTHONPATH. Then you can use absolute imports as well as the relative ones.
# script.py
form Module.util import _
You can put:
import sys
sys.path.insert(1, '.')
in your Module.__init__.py and then just import it in script.py with:
from Modules import util
Additionally you can define a __all__ = [] variable in your __init__ and then you can star import.
Simple question, but could not find the answer.
I've following structure:
./lib1:
main.py
./lib2:
__init__.py utils.py
From the root diretory, I'm running:
python lib1/main.py
and in main.py I want to import lib2/utils.py.
adding import lib2/utils.py fails.
One solution I found is to add:
~/tmp/root$ cat lib1/main.py
import sys,os
sys.path.append(os.getcwd())
import lib2.utils
lib2.utils.foo()
which is good, but I wander if there is other solution. Thanks.
Are lib1 and lib2 separate modules? If yes, the comment by #BrenBarn applies: You need to add the top directory (containing lib1 and lib2 to the Python path (e.g using PYTHONPATH environment variable or appending to sys.path).
If both lib1 and lib2 are part of one module (i.e. there is a __init__.py file in the top directory) you can use relative imports (https://docs.python.org/2.5/whatsnew/pep-328.html).
Your problem is caused by using the wrong directory structure. The main.py script should be in the same top-level directory as the package that it needs to import. So the structure should look like this:
project /
lib2 /
__init__.py
utils.py
other.py
main.py
The directory of the main script will always be added to the start of sys.path, so this will guarantee that any packages in that directory can be always be directly imported, no matter where the script is executed from.
To import the utils module into main.py (or other.py), you should do:
from lib2 import utils