所有文件在文件夹根目录下,如何用importlib.resources访问文件资源?
解决zipapp打包后读取根目录config.json的问题
为什么直接用路径找不到文件?
用python -m zipapp打包后,脚本是在ZIP归档内部运行的,此时用"config.json"这种相对路径,Python会去当前工作目录找文件,而不是ZIP包内部的根目录,所以必然找不到。
关于importlib.resources的使用细节
1. 包名与__init__.py的要求
importlib.resources是专门用来读取Python包内资源的工具,它要求你的代码所在目录是一个合法的Python包——也就是必须有__init__.py(空文件就行)。
如果你的所有代码都在根目录(没有子文件夹),那这个根目录就是你的包,包名就是你打包时的文件夹名称。比如你把所有文件放在my_script文件夹里,打包时执行python -m zipapp my_script,那代码里的包名就写"my_script"。
要是你直接在当前目录打包(没单独建文件夹),这种情况包名可以用''(空字符串),但还是得先建__init__.py才能让importlib.resources识别。
2. 不用纠结包名的替代方案
嫌搞包名麻烦?直接用__file__判断运行环境,读取ZIP包内的文件就行,不用__init__.py:
import os import zipfile # 获取当前脚本的绝对路径 current_script = os.path.abspath(__file__) # 判断是否在ZIP包(pyz文件)里运行 if current_script.endswith('.pyz'): with zipfile.ZipFile(current_script, 'r') as zip_ref: with zip_ref.open('config.json') as f: config_content = f.read().decode('utf-8') else: # 本地直接运行__main__.py时,读当前目录的config.json with open('config.json', 'r') as f: config_content = f.read()
这个方法不管是本地测试还是打包后运行都能正常工作。
3. 为什么__package__是空的?
直接运行python __main__.py时,脚本是作为主程序执行的,不是作为包的模块被导入,所以__package__为空是正常现象,依赖这个变量的方法在这里行不通。
用importlib.resources的标准流程
- 把所有脚本和
config.json放进一个单独的文件夹,比如my_app。 - 在
my_app里创建空的__init__.py。 - 打包:执行
python -m zipapp my_app,生成my_app.pyz。 - 在
__main__.py里写:
from importlib.resources import open_text with open_text('my_app', 'config.json') as f: config = f.read()
内容的提问来源于stack exchange,提问作者u84six
相关产品推荐
相关产品推荐

