在 Python 模块分发中查找文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:25:48  来源:igfitidea点击:

Finding a file in a Python module distribution

pythondistutils

提问by Paul

I've written a Python package that includes a bsddb database of pre-computed values for one of the more time-consuming computations. For simplicity, my setup script installs the database file in the same directory as the code which accesses the database (on Unix, something like /usr/lib/python2.5/site-packages/mypackage/).

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

How do I store the final location of the database file so my code can access it? Right now, I'm using a hack based on the __file__variable in the module which accesses the database:

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

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

It works, but it seems... hackish. Is there a better way to do this? I'd like to have the setup script just grab the final installation location from the distutils module and stuff it into a "dbconfig.py" file that gets installed alongside the code that accesses the database.

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

回答by Aaron Maenpaa

Try using pkg_resources, which is part of setuptools (and available on all of the pythons I have access to right now):

尝试使用 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'

There's more discussion about using pkg_resources to get resources on the eggspage and the pkg_resourcespage.

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

Also note, where possible it's probably advisable to use pkg_resources.resource_stream or pkg_resources.resource_string because if the package is part of an egg, resource_filename will copy the file to a temporary directory.

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

回答by éric Araujo

Use pkgutil.get_data. It's the cousin of pkg_resources.resource_stream, but in the standard library, and should work with flat filesystem installs as well as zipped packages and other importers.

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

回答by dguaraglia

That's probably the way to do it, without resorting to something more advanced like using setuptools to install the files where they belong.

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

Notice there's a problem with that approach, because on OSes with real a security framework (UNIXes, etc.) the user running your script might not have the rights to access the DB in the system directory where it gets installed.

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

回答by ankostis

Use the standard Python-3.7 library's importlib.resourcesmodule, which is more efficientthan setuptools:pkg_resources(on previous Python versions, use the backported importlib_resourceslibrary).

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

Attention:For this to work, the folder where the data-file resides must be a regular python-package. That means you must add an __init__.pyfile into it, if not already there.

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

Then you can access it like this:

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

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:
    ...