How script location, CWD, and relative imports interact

Scenario: A Modular Package Layout

Suppose you have this structure:

project_root/
├── main.py
├── package/
│   ├── __init__.py
│   ├── utils.py
│   └── logger/
│       ├── __init__.py
│       └── formatter.py

You want main.py to import from package.utils, and utils.py to import from logger.formatter.

Case 1: Running main.py Directly

bash

cd project_root
python main.py

✅ What Works

  • main.py can do:

    python

    from package import utils
    
  • utils.py can do:

    python

    from .logger import formatter  # ✅ relative import
    

Because:

  • sys.path[0] is project_root

  • package is a valid top-level package

  • Relative imports inside package work as expected

❌ Case 2: Running utils.py Directly

bash

cd project_root/package
python utils.py

❌ What Breaks

  • from .logger import formatter will raise:

    ImportError: attempted relative import with no known parent package
    

Because:

  • Python treats utils.py as a standalone script, not part of a package

  • Relative imports only work when the module is part of a package

✅ Solution: Use -m to Run as a Module

Instead of running utils.py directly, do:

bash

cd project_root
python -m package.utils

Now Python treats package as a proper package, and relative imports work.

Summary: Best Practices

Task Recommended Approach
Run top-level script python main.py from project root
Run submodule with imports python -m package.submodule from root
Avoid broken relative imports Don’t run submodules directly as scripts
Debug import issues Print sys.path and __name__

Bonus Tip: Debugging Imports

Add this to any script:

python

import sys
print("sys.path:", sys.path)
print("__name__:", __name__)

This helps you see:

  • Where Python is looking for modules

  • Whether the script is being run as __main__ or as part of a package

你可能感兴趣的:(python)