Python包内导入与单元测试导入异常问题求助
Hey there, let's work through this import issue you're facing with your nested package structure!
核心问题分析
The root of your problem comes down to how Python handles module imports when running test files directly. When you execute python tests/test_a.py, Python adds the tests/ directory to its module search path (sys.path) — not your project's root directory. This means it can't recognize package1 as a valid package, and the relative imports inside b.py (like from .a import Foo) will break when b is imported outside the context of its parent package.
解决方案
Here are a few clean, maintainable fixes tailored to your goal of using this as a nested super-package:
1. Use absolute imports in your test files (recommended)
First, make sure your project root is in Python's module search path. The easiest way to do this is to run your tests using the -m flag, which tells Python to treat your project as a package.
- Add an empty
__init__.pyfile to yourtests/directory (this makes it a sub-package, though it's optional if you use the-mflag, but it's good practice). - In your
test_a.py, use absolute imports pointing to your nested packages:from package1.a import Foo from package1.b import Bar # This will work because b's relative import is resolved within package1 - Run your tests from the project root with:
Or if you're not using pytest, just:python -m pytest tests/test_a.py -vpython -m tests.test_a
2. Use relative imports in test files (requires tests as a sub-package)
If you prefer relative imports in tests, you can structure tests as a sub-package and reference package1 from the parent level:
- Ensure
tests/has an__init__.pyfile. - In
test_a.py, use:from ..package1.a import Foo from ..package1.b import Bar - Run the test using the
-mflag from the project root, same as above.
3. Temporarily add the project root to sys.path (quick fix, less recommended)
If you need to run the test file directly without the -m flag, you can modify sys.path at the top of your test file to include the project root:
import sys from pathlib import Path # Add project root to sys.path sys.path.insert(0, str(Path(__file__).parent.parent)) from package1.a import Foo from package1.b import Bar
This works, but it's less clean than the first method because it hardcodes the path structure.
Key Takeaway
Relative imports like from .a import Foo only work when the module is imported as part of a package (not when run as a standalone script). By ensuring your project root is in sys.path (via the -m flag or explicit path addition) and using absolute or properly structured relative imports in tests, you'll resolve the import errors while keeping your nested package structure intact.
内容的提问来源于stack exchange,提问作者faulty_ram_sticks

