Quick answer: The attempted relative import error appears when Python executes a file as a top-level script even though its code uses package-relative syntax such as from .helpers import value. Keep the package layout intact and run the module from the project root with python -m package.module so Python knows its parent package.

ImportError: attempted relative import with no known parent package happens when Python sees an import such as from .tools import helper but the file is being run as a loose script instead of as part of a package. The leading dot only has meaning when Python knows the package name. Older runtimes may describe the same missing package context as ‘Parent module not loaded’; Fix SystemError Parent Module Not Loaded covers that wording and fix.
The usual fix is not to delete the dot blindly. First decide whether the code belongs inside a package. If it does, run the module from the project root with python -m package.module. If it does not, use absolute imports or move shared code into a real package.
This error often appears after code is split into several files. A helper that worked while everything lived in one script starts failing when it is moved under a package directory. That is a layout problem, not a syntax problem. Fix the way the module is launched so Python can calculate the package parent.
The official Python modules tutorial explains packages and intra-package references. The import system reference describes how Python resolves module names, and the __main__ documentation explains why direct script execution changes context.
Recognize The Package Layout
A relative import needs a package. A package directory normally contains an __init__.py file and is imported by name from its parent directory.
from pathlib import Path
project_files = [
Path("project/sample_app/__init__.py"),
Path("project/sample_app/cli.py"),
Path("project/sample_app/math_tools.py"),
]
for path in project_files:
print(path.as_posix())
In this layout, sample_app is the package. The parent directory named project should be your working directory when you run the module.
The exact package name comes from the directory imported by Python, not from the file you clicked in an editor. That distinction is why the same import can work in tests and fail when a single file is launched directly.
Run The Module With -m
Instead of running sample_app/cli.py directly, ask Python to run it as a module inside its package.
import sys
command = [
sys.executable,
"-m",
"sample_app.cli",
]
print("Run from the project root:")
print(command)
The -m form gives Python the package context needed for leading-dot imports. It also makes local development closer to how installed packages run in production.
In VS Code, PyCharm, and similar tools, configure the run target as a module when possible. If the interface only runs a file path, create a small project command or test that uses -m so the editor does not hide the real entry point.

Use Relative Imports Inside The Package
Relative imports are fine when files are inside the same package and the module is started correctly.
from .math_tools import add_numbers
def main():
result = add_numbers(2, 3)
print(result)
if __name__ == "__main__":
main()
This code belongs in sample_app/cli.py. It should be launched with the module command from the parent directory, not by double-clicking or directly executing the file path.
Use Absolute Imports For Clarity
An absolute import is often easier to read in application code because it starts from the package name.
from sample_app.math_tools import add_numbers
def calculate_total(items):
total = 0
for item in items:
total = add_numbers(total, item)
return total
print(calculate_total([1, 2, 3]))
Absolute imports work well after the package is installed, or when tests and commands run from the project root. They also make import paths easier to search across a codebase.
Check Runtime Context
When import behavior is confusing, print the runtime context. The package name tells you whether Python sees the file as part of a package.
import os
import sys
print("__name__:", __name__)
print("__package__:", __package__)
print("working directory:", os.getcwd())
print("first import path:", sys.path[0])
If __package__ is empty while the file uses leading-dot imports, the file was started without package context. Change the launch command before changing the imports.

Test The Entry Point
A small subprocess test can protect the import path. Run it from the project root in CI or during local checks.
import subprocess
import sys
completed = subprocess.run(
[sys.executable, "-m", "sample_app.cli"],
text=True,
capture_output=True,
check=False,
)
print(completed.returncode)
print(completed.stdout)
If the return code is not zero, inspect completed.stderr and confirm the test starts from the parent directory of the package.
Common Fixes That Work
Use python -m package.module from the project root when the file is part of a package. Add __init__.py to package directories when you need regular package behavior. Prefer absolute imports when a module is shared widely across the application.
Avoid patching sys.path at the top of every file. It can hide the real layout problem and make imports depend on the current working directory. If code must be shared by several projects, package it and install it into the environment instead.
Also avoid running package files directly from an editor button that uses the file path. Configure the editor to run the module, or create a small command that starts the package entry point. That keeps development, tests, and deployment aligned.
The key rule is simple: relative imports need package context. Once Python knows the package name, the leading dot has a clear parent and the error disappears.
If you are unsure which style to choose, prefer absolute imports for application modules and reserve relative imports for tightly related files inside the same package. That balance keeps imports readable while still allowing packages to move as a group.

Understand The Execution Context
A file launched as python path/to/module.py commonly has __name__ set to __main__ and no usable parent-package context. Relative imports need that context to resolve the leading dots. The same file may work when imported or run with -m because the module is then loaded as part of its package.
Use A Real Package Layout
Place an intentional package directory under the project root, keep modules in that package, and choose one documented entry point. Modern namespace packages do not always require __init__.py, but an explicit package structure still makes discovery, testing, and deployment easier to reason about.
Run With python -m
From the directory that contains the top-level package, run python -m package.module. This preserves the package name while still invoking the module’s main code. Avoid changing the working directory randomly or adding the module directory itself to sys.path as a permanent fix.

Choose Absolute Imports When Clearer
Absolute imports can make a package boundary explicit and may simplify a public entry point. They are not a universal replacement for relative imports; use the style that keeps the package’s ownership and dependency direction understandable.
Test The Same Entry Point You Deploy
Run unit tests, module execution, installed-package execution, and the production command from clean environments. Inspect __package__ only while diagnosing context, and test nested packages so an import succeeds for the right reason rather than because the developer’s working directory happens to add a hidden path.
The official Python import system reference explains package context and relative imports. The -m command-line reference documents module execution. Related guidance includes import paths and entry-point tests.
For related package boundaries, compare cross-file imports, subdirectory imports, and entry-point tests when keeping execution context consistent.
Frequently Asked Questions
Why does attempted relative import with no known parent package happen?
Python is executing the file as a top-level script, so it has no parent package context for an import such as from .helpers import value.
How do I fix the error?
Run the module from the project root with python -m package.module, keep the package layout valid, and invoke the intended entry point consistently.
Should I replace every relative import with an absolute import?
Not necessarily. Relative imports are useful inside a package; choose absolute imports when they make the package boundary and entry point clearer.
What does __package__ tell me?
It identifies the package context used for relative imports; inspect it while diagnosing execution mode, but do not patch it as a substitute for a correct entry point.