I have this package structure
project/
package_a/
__init__.py
subpackage_b/
__init__.py
module_one.py
subpackage_c
__init__.py
module_two.py
package_b/
module_one.py
def test_func():
return 0
How can I import test_func from module_two.py? I have tried using
from subpackage_b.module_one import test_func
from package_a.subpackage_b.module_one import test_func
from module_one import test_func
but none of them works, giving me ModuleNotFoundError. I understand there are many similar questions here but none of them seems to work for me. One which I have not tried is setting the PYTHONPATH variable, but I am not sure what to set it to. I am using VSCode and the current python.pythonPath is just the python file in my venv folder.
3 Answers 3
You can find the set of paths that you can import from using
import sys
print(sys.path)
So, make sure that the project path is in sys.path. If it is not, then you can add it dynamically in your code with the following line, which should be run before your import statements
sys.path.append('C:/Path_to_project/project')
However, if you were running python from the project folder, the path should already be there.
The proper way to import when your sys.path is including your project folder, would be
from package_a.subpackage_b.module_one import test_func
2 Comments
sys.path and indeed appending it allowed the import to succeed. However, I believe I am running it from the project folder so I am not sure why I have to append this in the first placeIn python, When the interpreter executes the import statement, it searches for module in a list of directories assembled from the following sources:
- The directory from which the input script was run, or the current directory if the interpreter is being run interactively
- The list of directories contained in the
PYTHONPATHenvironment variable, if it is set. (The format forPYTHONPATHis OS-dependent but should mimic thePATHenvironment variable.) - An installation-dependent list of directories configured at the time Python is installed (For example: in linux,
/usr/local/lib/python)
In addition, You can put the module file in any directory of your choice and then modify sys.path at run-time so that it contains that directory but this would not be a standard. you can do it for internal purpose but not a best practice to share your code with this.
Rather you can use python's __file__ attribute, to get the path and put it in sys.path like below:
import sys
from os.path import dirname
sys.path.append(dirname(__file__))
Comments
The root is of course your sys.path, and to answer why it does not work for you, I'll assume you attempt to invoke a python file from within your package, which will not allow python to find your package root properly.
Instead, invoke your code from a file directly in your project root (so the package is in the same directory as your main script file).
From https://docs.python.org/3/library/sys.html#sys.path
As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter.
$ tree
.
├── main.py
└── package_a
├── __init__.py
├── subpackage_b
│ ├── __init__.py
│ └── module_one.py
└── subpackage_c
├── __init__.py
└── module_two.py
# cat main.py
import package_a.subpackage_c.module_two
# cat package_a/subpackage_b/module_one.py
def test_func():
return 0
# cat package_a/subpackage_c/module_two.py
from package_a.subpackage_b.module_one import test_func
print("test func:", test_func())
$ python package_a/subpackage_c/module_two.py
Traceback (most recent call last):
File "package_a/subpackage_c/module_two.py", line 1, in <module>
from package_a.subpackage_b.module_one import test_func
ModuleNotFoundError: No module named 'package_a'
$ python main.py
test func: 0
ImportError: attempted relative import with no known parent package