从当前目录导入大量含__init__.py的包的最Pythonic方法
Great question! Let's break this down properly—you're right that plain from . import * doesn't work for subpackages by default, but we have two solid Pythonic ways to handle this, depending on your use case.
方法1:显式定义__all__(推荐固定子包场景)
The most Pythonic approach (aligning with the "explicit is better than implicit" mantra) is to define an __all__ list in your current directory's __init__.py. This tells Python exactly which subpackages to include when someone uses from . import *.
Add this to your root __init__.py:
__all__ = [ 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'x11', 'x12', 'x13', 'x14', 'x15', 'x16', 'x17', 'x18', 'x19', 'x20' ]
Then, in your code, you can import all 20 subpackages with a single line:
from . import *
This method is clean, readable, and gives you full control over what gets imported—other developers can immediately see which subpackages are exposed, no surprises.
方法2:动态自动导入(适合多变的子包集合)
If your subpackage list changes often (you add/remove them regularly) and you don't want to manually update __all__ every time, you can use Python's importlib and pkgutil modules to dynamically discover and import all subpackages.
Put this in your root __init__.py:
import importlib import pkgutil __all__ = [] # Iterate over all modules/subpackages in the current directory for _, pkg_name, is_package in pkgutil.iter_modules(__path__): if is_package: # Only process actual subpackages # Dynamically import the subpackage imported_pkg = importlib.import_module(f'.{pkg_name}', __name__) # Add it to __all__ so it's included in wildcard imports __all__.append(pkg_name) # Optional: Bind the subpackage to the current namespace globals()[pkg_name] = imported_pkg
This will automatically import any subpackage in the directory, no manual list required. A few caveats though:
- It's implicit, so you might accidentally import subpackages you didn't intend (like test or utility subpackages) — you'll need to add filtering logic if that's a concern.
- There's a tiny startup overhead, but it's negligible for 20 subpackages.
Which is the Most Pythonic Choice?
For your case with a fixed set of 20 subpackages, Method 1 is the clear winner. Explicitly listing them in __all__ makes your code transparent and follows Python's core philosophies. Reserve dynamic importing for scenarios where your subpackage list is truly dynamic and changes frequently.
Also, note that using from . import * is generally discouraged in regular modules, but it's widely accepted in a package's __init__.py as a way to create a clean, unified API for users of your package.
内容的提问来源于stack exchange,提问作者Ericson Willians

