无需__init__.py文件加载Python包内JSON Schema资源的方案
可行的无
__init__.py加载JSON Schema方案 方案1:用importlib.resources.files直接定位包路径(无需__init__.py)
Python 3.9+版本的importlib.resources.files支持直接通过包名字符串定位资源,不需要把schema目录转为可导入子包(不用加__init__.py)。示例代码:
from importlib import resources def _schema_file(self, uri: str): # 直接通过包的完整字符串路径定位,schema目录下无需额外文件 return resources.files("myapp.schema.v1") / uri
核心是传递包的字符串路径"myapp.schema.v1"而非导入子包,这样schema目录只需保留JSON Schema文件即可。
方案2:用pkgutil兼容低版本Python
如果需要兼容Python 3.8及以下版本,可使用pkgutil模块,同样不需要__init__.py:
import pkgutil import os def _schema_file(self, uri: str): # 获取包资源的目录路径 pkg_content = pkgutil.get_data("myapp.schema.v1", "") if not pkg_content: raise FileNotFoundError(f"Schema directory myapp.schema.v1 not found") # 拼接具体Schema文件的绝对路径 return os.path.join(os.path.dirname(pkg_content), uri)
注:pkgutil.get_data传递空字符串时会返回包目录下某个文件的内容,通过os.path.dirname可提取出目录路径。
方案3:配置setuptools的package_data(分发场景推荐)
如果用setuptools打包,可在配置文件中标记schema文件为包资源,确保打包时被包含,同时无需__init__.py:
在pyproject.toml中配置:
[project] name = "myapp" ... [tool.setuptools.package-data] "myapp.schema.v1" = ["*.json"]
或在setup.py中配置:
from setuptools import setup setup( name="myapp", ... package_data={ "myapp.schema.v1": ["*.json"], }, )
配置完成后,依然可以用importlib.resources.files("myapp.schema.v1")加载文件,且打包时会自动包含所有指定的Schema文件。
核心思路总结
- 不将schema目录转为可导入子包,直接通过包名字符串定位资源路径。
- 打包时必须通过
package_data配置确保Schema文件被包含进分发包。 - 优先使用
importlib.resources.files(Python 3.9+),有兼容性需求则用pkgutil。
内容的提问来源于stack exchange,提问作者Ken Williams
相关产品推荐
相关产品推荐

