32

我编写了一个 Python 包,其中包含一个 bsddb 数据库,其中包含一个用于更耗时的计算的预计算值。为简单起见,我的安装脚本将数据库文件安装在与访问数据库的代码相同的目录中(在 Unix 上,类似于 /usr/lib/python2.5/site-packages/mypackage/)。

如何存储数据库文件的最终位置以便我的代码可以访问它?现在,我正在使用基于__file__访问数据库的模块中的变量的 hack:

dbname = os.path.join(os.path.dirname(__file__), "database.dat")

它有效,但似乎...... hackish。有一个更好的方法吗?我想让安装脚本从 distutils 模块中获取最终安装位置,并将其填充到“dbconfig.py”文件中,该文件与访问数据库的代码一起安装。

4

4 回答 4

37

尝试使用 pkg_resources,它是 setuptools 的一部分(并且在我现在可以访问的所有 python 上都可用):

>>> import pkg_resources
>>> pkg_resources.resource_filename(__name__, "foo.config")
'foo.config'
>>> pkg_resources.resource_filename('tempfile', "foo.config")
'/usr/lib/python2.4/foo.config'

在egg页面和pkg_resources页面上有更多关于使用 pkg_resources 获取资源的讨论。

另请注意,可能建议使用 pkg_resources.resource_stream 或 pkg_resources.resource_string 因为如果包是鸡蛋的一部分,resource_filename 会将文件复制到临时目录。

于 2008-09-02T14:26:07.033 回答
19

使用pkgutil.get_data. 它是 的表亲pkg_resources.resource_stream,但在标准库中,应该与平面文件系统安装以及压缩包和其他导入程序一起使用。

于 2012-03-29T02:52:42.973 回答
3

这可能就是这样做的方法,而无需求助于更高级的方法,例如使用 setuptools 将文件安装到它们所属的位置。

请注意,这种方法存在问题,因为在具有真正安全框架(UNIX 等)的操作系统上,运行脚本的用户可能无权访问安装它的系统目录中的数据库。

于 2008-09-02T11:43:45.550 回答
3

使用标准 Python-3.7 库的importlib.resourcesmodule,它比 (在以前的 Python 版本上,使用 backported library )更有效setuptools:pkg_resourcesimportlib_resources

注意:为此,数据文件所在的文件夹必须是常规的 python-package。这意味着您必须在其中添加一个__init__.py文件,如果还没有的话。

然后你可以像这样访问它:

try:
  import importlib.resources as importlib_resources
except ImportError:
  # In PY<3.7 fall-back to backported `importlib_resources`.
  import importlib_resources


## Note that the actual package could have been used, 
#  not just its (string) name, with something like: 
#      from XXX import YYY as data_pkg
data_pkg = '.'
fname = 'database.dat'

db_bytes = importlib_resources.read_binary(data_pkg, fname)
# or if a file-like stream is needed:
with importlib_resources.open_binary(data_pkg, fname) as db_file:
    ...
于 2019-06-22T09:51:10.703 回答