Python导入模块中import语句工作机制及多场景正确导入方法
Hey there! This is such a common stumbling block with Python's import system—let me break down exactly what's happening here, then show you the fix.
To understand why you're seeing these errors, we need to cover two key parts of how Python finds and loads modules:
1. The Module Search Path (sys.path)
When Python runs a script, it looks for modules in the directories listed in sys.path. Here's the critical detail:
- If you run a script directly (like
python a.pyorpython module/b.py), the directory containing that script gets added to the start ofsys.pathautomatically.- When you run
a.pyfrom theproject/folder:sys.pathincludesproject/, so Python can see themodulepackage and everything inside it. - When you run
b.pydirectly from themodule/folder:sys.pathonly includesmodule/, notproject/—so Python has no idea themodulepackage even exists.
- When you run
2. Absolute vs. Relative Imports
Python has two main ways to import modules, and they behave differently depending on context:
- Absolute imports: Use the full path from a top-level package (e.g.,
from module import c). These work only if the parent directory of that top-level package is insys.path. - Relative imports: Use dots to reference sibling or parent modules (e.g.,
from . import c). These only work when the script is being run as part of a package (not as a standalone top-level script).
Why Your Original Code Failed
- When you used
import cinb.pyand rana.py: Python looked forc.pyinsys.path(which wasproject/), not inmodule/—hence theModuleNotFoundError. - When you switched to
from module import cinb.py:a.pyworked becauseproject/is insys.path, so Python could find themodulepackage. But runningb.pydirectly failed becausesys.pathwasmodule/, so Python couldn't locate themodulepackage itself.
You've got two solid options, depending on how you need to run b.py:
Option 1: Use Relative Imports + Run as a Package Module
This is the cleanest, most "Pythonic" approach for packages that are meant to be imported and occasionally run standalone.
In b.py, replace your import with a relative one:
# b.py from . import c # Rest of your code goes here
- This works perfectly when
b.pyis imported bya.py(since it's part of themodulepackage). - To run
b.pystandalone, don't run it directly. Instead, navigate to theproject/directory and run:
Thepython -m module.b-mflag tells Python to treatmodule.bas a package module, which addsproject/tosys.pathand lets the relative import work correctly.
Option 2: Add the Parent Directory to sys.path (For Direct Script Runs)
If you absolutely need to run b.py directly (without the -m flag), you can modify sys.path at the top of b.py to include the parent project/ directory:
# b.py import sys from pathlib import Path # Add the parent directory (project/) to the module search path sys.path.append(str(Path(__file__).parent.parent)) from module import c # Rest of your code goes here
- This makes the absolute import work both when
b.pyis imported bya.pyand when run directly. - Note: This is a bit of a workaround, but it's useful if direct script execution is a hard requirement.
Bonus Best Practice
For projects that need both importable packages and standalone scripts, a common pattern is to create a top-level scripts/ folder (next to module/) that imports from your package. This keeps your module files clean and avoids messing with sys.path inside them.
内容的提问来源于stack exchange,提问作者mannerpots

