提问人:Jagerber48 提问时间:7/6/2022 最后编辑:Jagerber48 更新时间:10/5/2022 访问量:3128
为什么使用 importlib.resources 而不是 __file__?
Why use importlib.resources over __file__?
问:
我有一个包裹,就像
mypkg
|-mypkg
|- data
|- data.csv
|- __init__.py # Required for importlib.resources
|- scripts
|- module.py
|- __init__.py
该模块需要执行特定任务。module.py
data.csv
我曾经访问的第一个幼稚方法是data.csv
# module.py - Approach 1
from pathlib import Path
data_path = Path(Path.cwd().parent, 'data', 'data.csv')
但是,当我们导入VIA或类似产品时,这显然会中断。我需要一种访问方式,无论从哪里导入。module.py
from mypkg.scripts import module
data.csv
mypkg
下一个幼稚的方法是使用属性来访问模块所在的路径。__file__
module.py
# module.py - Approach 2
from pathlib import Path
data_path = Path(Path(__file__).resolve().parents[1], 'data', 'data.csv')
然而,在研究这个问题时,我发现这种方法是不鼓励的。例如,请参阅如何从 Python 包内部读取(静态)文件?。
虽然对于这个问题的最佳解决方案似乎没有完全达成一致,但看起来可能是最受欢迎的。我相信这会是这样的:importlib.resources
# module.py - Approach 3
from pathlib import Path
import importlib.resources
data_path_resource = importlib.resources('mypkg.data', 'data.csv')
with data_path_resources as resource:
data_path = resource
为什么这个最终方法比?如果源代码被压缩,似乎不起作用。这是我不熟悉的情况,听起来也有点边缘。我不认为我的代码会以压缩方式运行。__file__
__file__
增加的开销似乎有点荒谬。我需要在数据文件夹中添加一个空,我需要导入,并且我需要使用上下文管理器来访问相对路径。importlib
__init__.py
importlib
关于该策略的好处,我错过了什么?为什么不直接使用?importlib
__file__
编辑:该方法的一个可能理由是它略微改进了语义。这应该被认为是包的一部分,所以我们应该使用类似的东西来访问它,但当然这种语法仅适用于导入 python 模块。但是将“从某个包导入某些内容”语义移植到更通用的文件类型。importlib
data.csv
from mypkg import data.csv
.py
importlib.resources
相比之下,构建相对路径的语法有点像是这样的:这个模块在文件结构中偶然靠近数据文件,所以让我们利用它来访问它。数据文件是包的一部分这一事实不会被利用。__file__
答:
您应该能够将这样的东西与:__file__
import csv
from io import StringIO
from pathlib import Path
import pkgutil
import sys
def main():
# Point to appropriate ancestor directory
p = Path(__file__).parent.parent.parent
sys.path.insert(0, str(p))
data = pkgutil.get_data('mypkg.data', 'data.csv')
reader = csv.reader(StringIO(data.decode()))
for row in reader:
print(row)
if __name__ == '__main__':
main()
如果文件包含data.csv
Col 1,Col 2
v1,v2
然后上面的脚本将打印出来
['Col 1', 'Col 2']
['v1', 'v2']
如果您选择“Shell”选项卡并运行 .python mypkg/scripts/module.py
评论
pkgutil
importlib_resources
__file__