Python Correct way of running modules
Links: 108 Python Index
Correct way of running modules¶
- Sample project structure
- Code inside
file1.py
- Code inside
file1.py
import sys
import pprint
pprint.pprint(sys.path)
from file1 import file1
print("hello from file2")
print(file1)
- Now if I try to run
python test-package/file2.py
it fails with the following error
['/Users/sarthaknarayan/Desktop/testfolder/module-test/test-package',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python310.zip',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10/lib-dynload',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10/site-packages']
Traceback (most recent call last):
File "/Users/sarthaknarayan/Desktop/testfolder/module-test/test-package/file2.py", line 6, in <module>
from file1 import file1
ModuleNotFoundError: No module named 'file1'
/Users/sarthaknarayan/Desktop/testfolder/module-test/test-package
so there is no way it can find file1.py
since it is outside of test-package
- The correct way of running file2.py
is by using -m
(module) flag in python.
- Running python -m test-package.file2
['/Users/sarthaknarayan/Desktop/testfolder/module-test',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python310.zip',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10/lib-dynload',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10/site-packages']
hello from file 1
hello from file2
10
- If we notice the path again we can see that this time our path is
/Users/sarthaknarayan/Desktop/testfolder/module-test
so python can findfile1.py
which is being imported infile2.py
Wrong way of solving the above problem using PYTHONPATH
¶
- We get no errors if we run
PYTHONPATH=$(pwd) python test-package/file2.py
['/Users/sarthaknarayan/Desktop/testfolder/module-test/test-package',
'/Users/sarthaknarayan/Desktop/testfolder/module-test',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python310.zip',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10/lib-dynload',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10/site-packages']
hello from file 1
hello from file2
10
- The main problem with this approach is that the path
/Users/sarthaknarayan/Desktop/testfolder/module-test/test-package
is still present and it is the first location from where python looks for packages. - This can lead to problems later if we wish to have 2 modules/files with the same name.
- Suppose my directory structure is something like this
- then
PYTHONPATH=$(pwd) python test-package/file2.py
will give the following error
['/Users/sarthaknarayan/Desktop/testfolder/module-test/test-package',
'/Users/sarthaknarayan/Desktop/testfolder/module-test',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python310.zip',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10/lib-dynload',
'/Users/sarthaknarayan/.pyenv/versions/3.10.0/lib/python3.10/site-packages']
Traceback (most recent call last):
File "/Users/sarthaknarayan/Desktop/testfolder/module-test/test-package/file2.py", line 6, in <module>
from file1 import file1
ImportError: cannot import name 'file1' from 'file1' (/Users/sarthaknarayan/Desktop/testfolder/module-test/test-package/file1.py)
- Note that it is trying to import
file1.py
fromtest-package
instead of importing it from the root directory.
Another Example¶
-
Directory structure
-
Python files
-
python -m package1.file2
works fine.
Making a package executable¶
- We can make a package executable by specifying
__main__.py
file under its directory. - You can have both
__init__.py
and__main__.py
files inside the same package- This setup will allow you to import it as a regular package and also make it essentially a CLI application.
References¶
Last updated: 2022-12-18