我有一个类似于以下结构的包:
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')
但是,当我们通过from mypkg.scripts import module
或类似方式导入module.py
时,这显然会出现问题。我需要一种方法来访问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__
?编辑:
importlib
方法的一个可能的理由是它具有稍微改进的语义。也就是说,data.csv
应该被视为包的一部分,因此我们应该使用类似from mypkg import data.csv
的方式访问它,但当然这个语法仅适用于导入.py
python模块。但importlib.resources
将“从某个包中导入某些内容”的语义移植到了更一般的文件类型。相比之下,从
__file__
构建相对路径的语法有点说:这个模块恰好靠近文件结构中的数据文件,因此让我们利用它来访问。未利用数据文件是包的一部分这一事实。
pkgutil
和importlib_resources
。 - aaron__file__
是可以的,而且很容易理解,所以如果它能用,我就应该直接使用它。如果我将来涉及到压缩应用程序,我想我需要更多地了解其他方法。 - undefined