Question

Relative Imports in Python 3: Why They Work Sometimes and Fail Other Times

pythonpython-3.xpython-import

Question

I want to import a function from another Python file in the same directory.

Usually, one of these import statements works:

from .mymodule import myfunction

or

from mymodule import myfunction

But the other form often fails with one of these errors:

ImportError: attempted relative import with no known parent package
ModuleNotFoundError: No module named 'mymodule'
SystemError: Parent module '' not loaded, cannot perform relative import

Why does this happen, and how does Python decide which import style is valid?

Short Answer

By the end of this page, you will understand the difference between relative imports and absolute imports in Python 3, why they behave differently depending on how a file is run, and how to structure your code so imports work reliably in real projects.

Concept

In Python, imports are not based only on file location. They also depend on how Python sees your code at runtime.

There are two common styles involved here:

from mymodule import myfunction

This is usually treated as an absolute import. Python looks for mymodule in places such as:

  • the current import path (sys.path)
  • installed packages
  • the project root, depending on how the program was started

And:

from .mymodule import myfunction

This is a relative import. The dot means:

  • "start from the current package"
  • import mymodule from the same package as this file

The key idea is that relative imports only work when the file is part of a package.

Why this matters

In real programs, Python modules are often organized into packages:

project/
├── app/
│   ├── __init__.py
│   ├── main.py
│   └── mymodule.py

If main.py is imported as part of package app, then this works:

from .mymodule import myfunction

But if you run main.py directly like this:

python main.py

then Python treats it as a top-level script, not as part of package app. In that case, . has no package context, so the relative import fails.

Why absolute imports also sometimes fail

This import:

from mymodule import myfunction

works only if Python can find mymodule on its import path.

If your file is inside a package, Python may expect you to refer to the full package path instead, such as:

from app.mymodule import myfunction

So the same two files can behave differently depending on:

  • where you run Python from
  • whether the file is executed directly or imported
  • whether the folder is treated as a package
  • what entries exist in sys.path

That is why one form sometimes works and the other fails.

Mental Model

Think of Python imports like giving directions to a building.

  • An absolute import is like giving the full street address.
    • Example: "Go to app.mymodule."
  • A relative import is like saying, "From where I am now, go next door."
    • Example: from .mymodule import myfunction

The problem is that "next door" only makes sense if Python knows where you currently are in the package structure.

If a file is run directly, Python often says, in effect:

  • "I know this is a script"
  • "I do not know its package neighborhood"

So a relative import like .mymodule becomes meaningless.

A useful rule of thumb:

  • Relative imports need package context
  • Absolute imports need a correct import path
Take Quiz

Syntax and Examples

Core syntax

Absolute import

from mymodule import myfunction

Or, inside a package-based project:

from app.mymodule import myfunction

Relative import

from .mymodule import myfunction

Parent-package relative import

from ..utils import helper

This means "go up one package level, then import utils."

Example project

project/
├── app/
│   ├── __init__.py
│   ├── main.py
│   └── mymodule.py

mymodule.py:

def myfunction():
    return "Hello from mymodule"

main.py:

from .mymodule import myfunction

print(myfunction())

This works when main.py is executed as a module from the project root:

python -m app.main

Why? Because Python now knows main.py belongs to the app package.

Example using absolute import

main.py:

from app.mymodule import myfunction

print(myfunction())

This also works when run from the project root:

python -m app.main

and often also when imported by other code in the project.

Beginner-friendly takeaway

If your code is inside a package, prefer imports that match the package structure. In many real projects, that means using:

from app.mymodule import myfunction

or running package code with:

python -m app.main

instead of running files directly from inside the package.

Step by Step Execution

Consider this structure:

project/
├── app/
│   ├── __init__.py
│   ├── main.py
│   └── mymodule.py

mymodule.py:

def myfunction():
    return 42

main.py:

from .mymodule import myfunction

result = myfunction()
print(result)

What happens when you run this?

Case 1: Run directly

python app/main.py

Step by step:

  1. Python starts main.py as the top-level script.
  2. Its module name becomes something like __main__.
  3. Python does not treat it as part of package app.
  4. The statement from .mymodule import myfunction asks for a relative import.
  5. Relative import needs a known parent package.
  6. No parent package is known.
  7. Python raises:
ImportError: attempted relative import with no known parent package

Case 2: Run as a module

python -m app.main

Step by step:

  1. Python starts from the project root.
  2. It loads app.main as a module inside package app.
  3. Now Python knows the parent package is app.
  4. from .mymodule import myfunction means "import mymodule from app."
  5. Python finds app/mymodule.py.
  6. myfunction() runs.
  7. Output is:
42

This is the same code, but a different execution context. That context changes whether the import is valid.

Real World Use Cases

Package-based applications

Large Python applications are usually split into packages:

  • API routes
  • database code
  • utility modules
  • configuration modules

Relative imports can help connect modules inside the same package.

Reusable libraries

When building a library, modules often import nearby helpers:

from .helpers import parse_data
from .config import DEFAULT_TIMEOUT

This makes it clear those modules belong to the same package.

Command-line tools

CLI tools often fail with import errors when developers run a file directly instead of running the package correctly.

For example, this may fail:

python tool/main.py

while this works:

python -m tool.main

Test suites

Tests often expose import problems because they may run from a different working directory. Using a clean package structure and consistent imports helps avoid environment-specific bugs.

Web applications

Framework-based apps often rely on package imports across folders such as:

  • models
  • services
  • routes
  • utils

Understanding import rules helps you avoid fragile code that only works when started from one exact folder.

Take Quiz

Real Codebase Usage

In real codebases, developers usually avoid import confusion by following a few practical patterns.

1. Use a clear package structure

project/
├── myapp/
│   ├── __init__.py
│   ├── api.py
│   ├── services.py
│   └── utils.py

Then import using package-aware paths.

2. Prefer absolute imports for readability

Many teams prefer:

from myapp.utils import helper

because it is explicit and easier to understand in larger projects.

3. Use relative imports for closely related modules

Some projects use relative imports within a package:

from .utils import helper

This can be convenient when refactoring package names, but it depends on code being run inside package context.

4. Avoid running package files directly

Instead of:

python myapp/api.py

use:

python -m myapp.api

This is a very common real-project rule.

5. Keep entry points separate

A common pattern is to have a top-level runner file:

project/
├── run.py
├── myapp/
│   ├── __init__.py
│   └── main.py

run.py:

from myapp.main import start

start()

This avoids directly executing files inside the package.

6. Avoid manually editing sys.path

Beginners sometimes fix imports by adding folders to sys.path. This may work temporarily, but it usually makes code harder to maintain and test.

Common Mistakes

1. Running a package module as a plain script

Broken example:

python app/main.py

with:

from .mymodule import myfunction

Why it fails:

  • Python does not know main.py belongs to package app

Better:

python -m app.main

2. Assuming "same directory" is enough

Broken thinking:

  • "These files are next to each other, so import should always work."

In Python, imports depend on module/package context, not just physical file placement.

3. Using absolute imports without the package name

Broken example:

from mymodule import myfunction

inside a package where the correct import should be:

from app.mymodule import myfunction

Why it fails:

  • Python searches for a top-level module named mymodule
  • It may not exist on the import path

4. Forgetting package structure

If your code is meant to be a package, organize it like one.

Example:

app/
├── __init__.py
├── main.py
└── mymodule.py

While modern Python supports namespace packages in some cases, beginners usually get more predictable behavior with a clear package layout.

5. Mixing execution styles

A file may appear to work in one environment and fail in another because it is started differently.

For example:

  • IDE run button
  • terminal command
  • test runner
  • framework launcher

Always ask: How is this module being executed?

6. Fixing imports by copying files or changing directories randomly

This often hides the real problem instead of solving it. A reliable fix is to:

  • choose a package structure
  • use consistent imports
  • run code from the project root

Comparisons

ConceptExampleWhen it worksMain advantageMain risk
Absolute importfrom app.mymodule import myfunctionWhen app is on the import pathClear and explicitCan fail if project root is not used correctly
Simple top-level importfrom mymodule import myfunctionWhen mymodule is directly discoverable on sys.pathShort syntaxAmbiguous in larger projects
Relative importfrom .mymodule import myfunctionOnly when current file is part of a packageGood for nearby modulesFails when file is run directly

Relative vs absolute imports

QuestionRelative importAbsolute import
Depends on package context?YesLess directly
Easy to read in large projects?SometimesUsually yes
Safe to run file directly?NoSometimes, but not always
Good for reusable packages?Yes, if package is run correctlyYes

Direct script run vs module run

Run styleExamplePackage context available?
Direct scriptpython app/main.pyUsually no
Module executionpython -m app.mainYes
Take Quiz

Cheat Sheet

# Absolute import
from app.mymodule import myfunction

# Relative import: same package
from .mymodule import myfunction

# Relative import: parent package
from ..utils import helper

Rules to remember

  • . means "current package"
  • .. means "parent package"
  • Relative imports work only inside a package context
  • Running a file directly usually removes that package context
  • python -m package.module preserves package context

Common errors

ImportError: attempted relative import with no known parent package
  • You used a relative import in a file Python is treating as a standalone script.
ModuleNotFoundError: No module named 'mymodule'
  • Python cannot find mymodule on the import path.
SystemError: Parent module '' not loaded, cannot perform relative import
  • Python does not know the parent package for a relative import.

Safe habits

  • Run code from the project root
  • Use python -m package.module for package modules
  • Prefer clear package structure
  • Use absolute imports when clarity matters
  • Do not rely on current directory accidents

FAQ

Why does from .mymodule import myfunction fail when I run the file directly?

Because relative imports require Python to know the module's parent package. When you run a file directly, Python usually treats it as a standalone script, not as part of a package.

Why does from mymodule import myfunction sometimes work?

It works when mymodule is available on Python's import path. That can depend on your current working directory, project layout, or environment.

Should I use relative or absolute imports in Python?

Both are valid. Absolute imports are often clearer in larger projects. Relative imports are useful for closely related modules inside a package.

What does python -m app.main do differently?

It runs main as a module inside the app package, so Python keeps package context and relative imports can work.

Do I need __init__.py?

In many beginner-friendly package layouts, yes, it helps make package structure explicit and avoids confusion.

Why does my import work in my IDE but fail in the terminal?

Your IDE may set a different working directory or modify the import path. The terminal may be running the file in a different context.

Can I fix this by changing sys.path manually?

You can, but it is usually not the best solution. It makes code harder to understand and less portable. A proper package structure is usually better.

Take Quiz

Mini Project

Description

Build a small Python package with two modules where one module imports a function from the other. This project demonstrates the difference between package-aware execution and direct script execution, which is the root cause of many relative import errors.

Goal

Create a package that prints a greeting by importing a helper function correctly using package-aware imports.

Requirements

  1. Create a package folder named app.
  2. Add a module named helpers.py with one function that returns a greeting.
  3. Add a module named main.py that imports and prints the greeting.
  4. Make the import work using proper package execution.
  5. Run the program from the project root.
Take Quiz

Keep learning

Related questions

View more