Explain Codes LogoExplain Codes Logo

Importing files from different folder

python
sys-path
absolute-imports
best-practices
Nikita BarsukovbyNikita Barsukov·Aug 9, 2024
TLDR

For a quick solution to import files from a separate folder, append to sys.path in Python.

import sys sys.path.append('/path/to/folder') from target_module import desired_function

This code tells Python to look for importable files in the directory /path/to/folder, in addition to its system-defined locations.

Working with sys.path

Python searches for modules to import along paths listed in sys.path. This list includes the current script's directory, locations specified in the PYTHONPATH environment variable, and Python's standard library.

Adding a directory to sys.path:

import sys sys.path.append('relative/path/to/your/module') # Like sending Python on a treasure hunt!

It points Python's import mechanism to additional locations. This tip is great for quick and dirty solutions, but not for robust, long-living code.

Coding with style: Import statements

Best practices recommend to:

  1. Structure your code in packages.
  2. Use absolute imports as often as possible.
  3. Use relative imports sparingly.

Organizing code in packages—directories with an __init__.py file—tells Python to treat these directories as containers for Python files or modules, akin to a travel bag for all your script goodies.

Here's an example project structure using packages:

my_super_project/  # Keep the capes in this closet
|-- my_super_package/
|   |-- __init__.py
|   |-- my_super_module.py
|-- my_app.py

To import a function from my_super_module.py in my_app.py, you'd write:

from my_super_package.my_super_module import my_super_function # Super easy, right?

Understanding relative and absolute imports

When it comes to imports, we have two key players:

  • Absolute imports - The full-timers who use the entire project's structure in their paths:
from my_super_project.my_super_package.my_super_module import my_super_function
  • Relative imports - The freelancers who reference modules using their relation to the current file's location:
from .my_super_module import my_super_function # Sibling modules from ..my_super_package import another_module # Uncle modules, always up about something

Executing scripts in packages

Running scripts in a package requires knowledge of the -m flag with Python:

python -m my_super_package.my_super_module

This treats the module as a script while understanding the package's structure, lowering the risk of weird ImportError issues.

On the move with sys.path

While directly modifying sys.path is seen as a workaround, sometimes it's the easiest way. Use sys.path.insert(0, '/path/to/dojo') to prepend a directory, sys.path.append('/path/to/dojo') to add it to the end. This is akin to Python's “I know kung fu” moment a la The Matrix.

Once a module is imported, it's like your own Mr. Miyagi, instructing your code no matter how sys.path changes.

Troubleshooting common errors

Module not found?

Bogus ImportError? Check your sys.path entry for pesky typos, or invisible force fields around your target module.

Module name clashes

Avoid unnecessary sword fights! If your module shares a name with a built-in or third-party module, Python may import the wrong one. Remember, there can be only one random.py module importable by import random.

Altering PYTHONPATH

Unlike Captain Hook, Python has another hand. The PYTHONPATH environment variable is another way to add directories to the search path system-wide or for your session:

export PYTHONPATH=/path/to/wonderland:$PYTHONPATH # Alice's UNIX way

On Windows:

set PYTHONPATH=C:\path\to\wonderland;%PYTHONPATH% # Windows looking glass

This goes beyond direct sys.path edits by affecting all Python processes. Like a treasure map, use it carefully!