Python Import from Another Directory (5 Ways That Work)

For a Python import from another directory, the cleanest fix is to make the folder a package and run your script as a module from the project root with python -m. Python then finds sibling folders automatically:

store/
    utils/pricing.py
    app/main.py        # contains: from utils.pricing import add_tax

cd store
python -m app.main

I built that small project for real and ran every command with Python 3.12.5 in Command Prompt, errors included.

Here I’ll explain why the import fails, then show five fixes: python -m, sys.path, PYTHONPATH, importlib for a file path, and relative imports done right.

Why can’t Python import from another directory?

When you run python app\main.py, Python adds the script’s own folder, app, to the search path. It doesn’t add the project root, so a sibling folder like utils is invisible:

from utils.pricing import add_tax

print(f"Total with tax: ${add_tax(80.00):.2f}")

Output:

Traceback (most recent call last):
  File "C:\pyguides\store\app\main.py", line 1, in <module>
    from utils.pricing import add_tax
ModuleNotFoundError: No module named 'utils'
Total with tax: $86.60
Command Prompt output of ModuleNotFoundError No module named utils when running app/main.py directly, then success with python -m app.main
Run as a file, Python can’t see utils. Run as a module from the project root, it can.

With python -m app.main, the current folder (the project root) goes on the path instead. Empty __init__.py files in app and utils mark them as packages.

Fix 2: Add the folder to sys.path

If you need to run a script directly, insert the project folder into sys.path before the import. Build the path from __file__ so it works from any current directory:

import sys
from pathlib import Path

PROJECT = Path(__file__).resolve().parent.parent     # the folder above scripts\
sys.path.insert(0, str(PROJECT))

from utils.pricing import add_tax

print("project folder on sys.path:", sys.path[0].endswith(PROJECT.name))
print(f"Austin order total: ${add_tax(250.00):.2f}")

Output:

project folder on sys.path: True
Austin order total: $270.62
Command Prompt output of a Python script adding its parent folder to sys.path and importing utils from another directory
The script finds utils because its parent folder is now first on sys.path.

It works, but it’s a bit of a hack, and linters dislike imports below other code. For the one-level-up case, see importing from a parent directory.

Fix 3: Set the PYTHONPATH environment variable

PYTHONPATH adds folders to the search path without touching your code. Here tools\check.py imports money from a shared folder:

from money import cents

print("$19.99 is", cents(19.99), "cents")

Output:

Traceback (most recent call last):
  File "C:\pyguides\store\tools\check.py", line 1, in <module>
    from money import cents
ModuleNotFoundError: No module named 'money'
$19.99 is 1999 cents
Command Prompt output of a ModuleNotFoundError, then a successful import after setting PYTHONPATH to the shared folder
Without PYTHONPATH the import fails; with it, shared is searched too.

On macOS and Linux it’s export PYTHONPATH=shared. In VS Code you can set it in a .env file. More in environment variables in Python.

Fix 4: Import a module from a file path with importlib

Sometimes the file isn’t in a package at all, like a vendored script with a fixed path. importlib.util loads it directly:

import importlib.util
from pathlib import Path

path = Path("vendor") / "legacy_rates.py"
spec = importlib.util.spec_from_file_location("legacy_rates", path)
legacy = importlib.util.module_from_spec(spec)
spec.loader.exec_module(legacy)

print(legacy.STATE_TAX["TX"], legacy.STATE_TAX["CA"])

Output:

0.0625 0.0725

I keep this for plugins and one-off loaders. For normal project code, packages and -m are much easier to maintain.

Fix 5: Relative imports (and the no known parent package error)

Inside a package, from .helpers import money means “from this package”. It only works when Python knows the package, which a directly run file doesn’t:

from .helpers import money

print("Formatted:", money(1234.5))

Output:

Traceback (most recent call last):
  File "C:\pyguides\store\app\relative.py", line 1, in <module>
    from .helpers import money
ImportError: attempted relative import with no known parent package
Formatted: $1,234.50
Command Prompt output of ImportError attempted relative import with no known parent package, fixed by running python -m app.relative
Same file, two commands. Only python -m gives the module a parent package.

Which way to import from another directory?

ApproachWhen to use it
Package + python -mYour own project; the standard choice
pip install -e .Bigger projects with a pyproject.toml; imports work from anywhere
sys.path.insert()Quick scripts you run directly
PYTHONPATHTooling, CI, editors, without code changes
importlibLoading a file by path, plugins

For files in the same folder, none of this is needed; see importing a file from the same directory.

Related import and setup guides:

Frequently asked questions

How do I import a module from another directory in Python?

Make the folders packages, then run from the project root with python -m app.main. Or add the folder to sys.path or PYTHONPATH.

Why do I get ModuleNotFoundError for my own folder?

Python only searches the running script’s folder, installed packages and PYTHONPATH. A sibling folder isn’t on that list.

Do I still need __init__.py files?

Not strictly, since namespace packages work without them, but adding empty __init__.py files makes the structure explicit and avoids surprises.

How do I fix attempted relative import with no known parent package?

Run the file as a module from the project root, like python -m app.relative, or switch to an absolute import.

Is sys.path.append bad practice?

It’s fine for small scripts. In larger projects, prefer packages, python -m or an editable install.

Where does Python look for modules?

The search order is explained in The Module Search Path in the Python tutorial.