python tricks

How to import a locally available module if you only know its relative location

Using relative paths in Python can be a bit tricky because it depends on where you run your script from. Let's assume we have the following directory structure:


```

project/

├── main_directory/

│   ├── main_script.py

├── module_directory/

│   ├── my_module.py

│   ├── __init__.py

```


Here, `main_script.py` is the script where you want to import `my_module.py`, and these two scripts are in different directories (`main_directory` and `module_directory` respectively) but under the same parent directory `project`.


**Step 1:** First, you need to find out the relative path from `main_script.py` to `my_module.py`. In this case, the relative path is `../module_directory/my_module`.


**Step 2:** Then, you add this relative path to `sys.path` in `main_script.py`:


```python

import sys

import os


# Get the absolute path of the directory of the script being run:

dir_path = os.path.dirname(os.path.realpath(__file__))


# Add the relative path to sys.path

sys.path.insert(0, os.path.join(dir_path, '../module_directory'))


import my_module  # Now this import should work

```


In the script above, `os.path.dirname(os.path.realpath(__file__))` gets the directory that `main_script.py` is in, as an absolute path. `os.path.join(dir_path, '../module_directory')` joins this absolute path with the relative path to `module_directory`, effectively giving an absolute path to `module_directory`.


Note that the `os.path.join()` function is used to join paths in a way that uses the correct path separator for the current operating system. This is generally a good practice to follow for code portability.


Also, `os.path.realpath()` resolves any symbolic links. If the script is a symbolic link (or shortcut, in Windows terms), this will give the location of the file it points to, not the link itself.


Finally, `import my_module` should work because `module_directory` has been added to `sys.path`.


Note that this method modifies `sys.path` only for the duration of the script run. The `sys.path` modification doesn't persist after the script finishes.

Comments