我正在编写一个包含需要在./data/
子目录中打开数据文件的模块的python包.现在我有了硬编码到我的类和函数中的文件的路径.我想编写更强大的代码,可以访问子目录,无论它在用户系统上的安装位置如何.
我尝试了各种各样的方法,但到目前为止我没有运气.似乎大多数"当前目录"命令都返回系统的python解释器的目录,而不是模块的目录.
这似乎应该是一个微不足道的常见问题.但我似乎无法弄明白.部分问题是我的数据文件不是.py
文件,所以我不能使用导入功能等.
有什么建议?
现在我的包目录看起来像:
/ __init__.py module1.py module2.py data/ data.txt
我试图访问data.txt
距离module*.py
谢谢!
执行此操作的标准方法是使用setuptools包和pkg_resources.
您可以根据以下层次结构布置包,并根据以下链接配置包安装文件以将其指向您的数据资源:
http://docs.python.org/distutils/setupscript.html#installing-package-data
然后,您可以使用pkg_resources重新查找和使用这些文件,具体链接如下:
http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access
import pkg_resources DATA_PATH = pkg_resources.resource_filename('', 'data/') DB_FILE = pkg_resources.resource_filename(' ', 'data/sqlite.db')
您可以使用下划线 - 下划线 - 文件 - 下划线 - 下划线(__file__
)来获取包的路径,如下所示:
import os this_dir, this_filename = os.path.split(__file__) DATA_PATH = os.path.join(this_dir, "data", "data.txt") print open(DATA_PATH).read()
To provide a solution working today. Definitely use this API to not reinvent all those wheels.
A true filesystem filename is needed. Zipped eggs will be extracted to a cache directory:
from pkg_resources import resource_filename, Requirement path_to_vik_logo = resource_filename(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png")
Return a readable file-like object for the specified resource; it may be an actual file, a StringIO, or some similar object. The stream is in “binary mode”, in the sense that whatever bytes are in the resource will be read as-is.
from pkg_resources import resource_stream, Requirement vik_logo_as_stream = resource_stream(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png")
Package Discovery and Resource Access using pkg_resources
https://setuptools.readthedocs.io/en/latest/pkg_resources.html#resource-extraction
https://setuptools.readthedocs.io/en/latest/pkg_resources.html#basic-resource-access
我想我已经找到了答案.
我创建了一个模块data_path.py,我将其导入到包含以下内容的其他模块中:
data_path = os.path.join(os.path.dirname(__file__),'data')
然后我打开我的所有文件
open(os.path.join(data_path,'filename'), )
你需要一个整个模块的名称,你给的目录树没有列出那个细节,对我来说这个工作:
import pkg_resources print( pkg_resources.resource_filename(__name__, 'data/data.txt') )
值得注意的是,setuptools似乎不会根据与打包数据文件的名称匹配来解析文件,因此,无论如何,你都必须包含data/
前缀.os.path.join('data', 'data.txt)
如果需要备用目录分隔符,可以使用,但通常我发现硬编码的unix样式目录分隔符没有兼容性问题.