I have a project like:
project/
foo/
other.py
bar/
baz.py
If I code something like:
import sys
sys.path.insert(0, '../foo')
from foo import other
It doesn't work. But if I move foo into the bar directory it works. I realize this is bad code style, but how is this relative path searched and where does the documentation define it?
from foo import other will append foo to each of the directories in sys.path. So it's looking for ../foo/foo/other.py, but the actual path is just ../foo/other.py.
You should just insert .. into sys.path, then it will look for ../foo/other.py. Or if you only want to include that directory in the path, just use import other, without from foo.
Assuming you are in the baz directory, you need to include your parent directory .. in the path. Then when you do from foo, the foo directory in your parent directory is found.
This works:
import sys
sys.path.insert(0, '..')
from foo import other
Read more:
Stackoverflow Answer
The Definitive Guide to Python import Statements
Alternatively, since you included ../foo in the path, you could simply do import other, like so:
import sys
sys.path.insert(0, '..\foo')
import other
Related
Original project foo:
/foo
/module_a
/module_aa
/module_b
...
Where in the original project, module_b contains imports such as import module_a
In the new project, bar I'd like to have:
/bar
app.py
/foo
/module_a
/module_aa
/module_b
...
However, this breaks the imports in the foo subdirectory:
File "/bar/foo/module_b"
import module_a
ModuleNotFoundError: No module named 'module_a'
What should I do here, to avoid having to update/modify all of the import statements in the foo directory?
This is what relative imports are for. Change
import module_a
to
import .module_a
so that module_b will look in its own package for module_a, rather than in a directory on the Python search path that no longer contains module_a.
This is the cleanest I was able to get it working without modifying any of the original codebase:
/foo/__init__.py
import sys
sys.path.append("../foo")
from module_a import some_function_a
from module_b import some_other_function_b
sys.path.remove("../foo")
app.py
import foo
foo.somefunction_a()
foo.some_other_function_b()
I have a directory like this:
-RootFolder/
- lib/
- file.py
- source/
- book.py
I'm at the book.py, how do I import a class from the file.py?
When you are running book.py, only it's directory is gonna be added to the sys.path automatically. You need to make sure that the path to the RootFolder directory is in sys.path(this is where Python searches for module and packages) then you can use absolute import :
# in book.py
import sys
sys.path.insert(0, r'PATH TO \RootFolder')
from lib.file import ClassA
print(ClassA)
Since you added that directory, Python can find the lib package(namespace package, since it doesn't have __init__.py)
If you start your program from RootFolder (e.g. python -m source.book), the solution by Irfan wani should be perfectly fine. However, if not, then some hacking is required, to let Python know lib also contains relevant code:
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent / "lib"))
import file
from lib.file import some_module
I think this should work fine if the rootfolder is added to path.
If not, we need to do that first as shown by #Amadan and #SorousH Bakhtiary (just wanted to add some explanation);
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))
So here, Path(__file__) gives the path to the file where we are writing this code and .parent gives its parent directory path and so on.
Thus, str(Path(__file__).parent.parent) gives us path to the RootFolder and we are just adding that to the path.
I have a directory structure like this
-project
--folder1
---file1.py
--folder2
---file2.py
How can I import a function from file2 and use it in file1?
I tried to
import sys
sys.path.insert(0, '../folder2/')
from file2 import foo
foo()
and this doesn't work.
I tried to include __init__.py in each folder at it didn't work either.
Do I have an error with the relative path, or what should I do?
For a simple solution you can add the "absolute" path to the project directory and then put from folder2.file2 import foo in file1.py like :
import sys
sys.path.insert(0, <absolute path to "project" direcotry>)
from folder2.file2 import foo
foo()
now you can run your file1.py directly, python will find folder2 and therefore file2.
Alternatively you can add the "absolute" path to the folder2 directory and then put from file2 import foo in file1.py like:
import sys
sys.path.insert(0, <absolute path to "project" folder2>)
from file2 import foo
foo()
now you can run your file1.py directly, python will find file2.
use import folder2.file2 or from folder2.file2 import function_name
PS: Your project directory should be in python path
I've been looking around this site for how I can import a class stored in a folder at the same hierarchy level. What I found is that using .. should bring me up one folder. Or at least, that is how I read it as that assumption seems to be wrong.
src/
folderStrucutre1/
__init__.py
fileToImport.py <- contains A
folderStrucutre2/
someFile.py
__init__.py
abc.py
Having above folder structure in which fileToImport.py contains a class named A. How would I import A into someFile.py?
Due to how packages work in python, you need to move src and abc.py into a subfolder, and provide an __init__.py for it.
The directory structure should look like this after the changes:
package-name/
package-name/
folderStructure1/
__init__.py
fileToImport.py <- contains A
folderStructure2/
__init__.py
someFile.py
__init__.py
abc.py
Then, in someFile.py you can import A using a relative import from the parent package:
from ..folderStructure1.fileToImport import A
Lastly, you should open the topmost folder (parent to abc.py) for IDE intellisense to work
First, we need to create the absolute path to your src folder without hard-coding it in your script to make it portable.
Add this code in your someFile.py file.
import os
src_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Now, let's add your folderStructure1 directory to the Python Search Path
import sys
sys.path.append(src_path + '/folderStructure1')
Now you can use the following:
from fileToImport import Class
object = Class()
You can add src to the python search path and then you can import A from fileToImport.py.
For this, you should write someFile.py like:
import sys
sys.path.append("..") # .. represente the father folder
from folderStrucutre1.fileToImport import A
instance_for_A = A()
There are quite a few questions regarding python relative paths, but I have not found anything for the following situation:
src/
__init__.py
notebook.ipynb
A/
__init__.py
foo.py
B/
__init__.py
bar.py
I'm trying to import in notebook.ipynb:
from A.foo import Foo
which has a subdirectory/subpackage import to make:
foo.py
from ..B.bar import Bar
I'm getting a ValueError: Attempted relative import beyond toplevel package.
If I had only a few files, I would try to hack a solution using sys and os. However, I got quite a few in deeper directories and am looking for a more elegant way. Any ideas?
I saw that you said you are looking for a more elegant solution than using sys, however using sys gives a solution for this example.
foo.py:
import sys
sys.path.append('..')
from A.foo import foo
notebook.ipynb
import sys
sys.path.append('..')
from B.bar import Bar