Searching path of packages and modules
1
2
3
4
5
6
7
8
9
10
11
| >>> import sys
>>> for i in range(len(sys.path)):
... print(sys.path[i])
...
/usr/lib/python38.zip
/usr/lib/python3.8
/usr/lib/python3.8/lib-dynload
/home/vma/.local/lib/python3.8/site-packages
/usr/local/lib/python3.8/dist-packages
/usr/lib/python3/dist-packages
|
Package and Modules
There is this example package from one entries of searching path.
1
2
| $ find /usr -name urllib -type d
/usr/lib/python3.8/urllib
|
Packages are directories in sys.path contain other packages/modules, at least a module as __init__.py.
1
2
3
4
5
6
7
8
9
10
11
12
| >>> import urllib
>>> type(urllib) # this is shown as module
<class 'module'>
>>> import urllib.request # this is also shown as module
>>> type(urllib.request)
<class 'module'>
>>> urllib.__path__ # but urllib is actually a package(folder)
['/usr/lib/python3.8/urllib'] # Same location you found from bash above
>>> urllib.reqeust.__path__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'urllib' has no attribute 'reqeust'
|
import a module from some where
Create yourself a module
1
2
3
| $ cat not_path/test_module.py
def found():
print("Python found this module")
|
Directly modify sys.path to add a path can load this module
1
2
3
4
5
6
7
8
9
10
11
| >>> import test_module
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'test_module'
>>> import sys
>>> sys.path.append('not_path')
>>> import test_module
>>> test_module.found()
Python found this module
>>> [p for p in sys.path if 'not_path' in p]
['not_path']
|
another way is $PYTHONPATH environment variable will be added to sys.path when python is started
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| $ echo $PYTHONPATH
$ export PYTHONPATH=not_path
$ echo $PYTHONPATH
not_path
$ python3
Python 3.8.10 (default, Nov 14 2022, 12:59:47)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> [p for p in sys.path if 'not_path' in p]
['/home/vma/decmaxn.github.io/not_path']
>>> import test_module
>>> test_module.found() # Use a method of the module to prove module is imported properly
Python found this module
|
Import a package and module
Let me move the module inside package
1
| $ mv not_path/test_module.py not_path/package/
|
You have to import the module with a package name now, and you have to call it with the package name.
1
2
3
4
5
6
7
8
9
10
11
12
13
| >>> import package # Import package alone
>>> package.test_module.found() # won't includes it's modules yet
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'package' has no attribute 'test_module'
>>> import package.test_module # specifically import the module ...
>>> package.test_module.found() # makes it work
Python found this module
>>> test_module.found() # Can't call module name alone yet
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'test_module' is not defined
>>>
|
Note importing the package won’t include it’s modules above.
Import package will run __init__.py under it.
1
2
3
| $ echo "print('package is being imported')" > not_path/package/__init__.py
$ ls not_path/package/
__init__.py
|
__init__.py is run when package is imported
1
2
3
4
| >>> import package
package is being imported
>>> package.__file__
'/home/vma/decmaxn.github.io/not_path/package/__init__.py'
|
This can be used to avoid importing each modules in the package one by one
1
| $ echo "from package.test_module import found as fd" >> not_path/package/__init__.py
|
Let’s import the method of a moudle directly, bypassing the module, to the package.
1
2
3
4
| >>> import package
package is being imported
>>> package.fd() # The as name of found method is attached directly to the package
Python found this module
|
This way can be used to simplify long pathes of package/module…