管理 Python 项目中的资源
我有一个 Python 项目,其中使用了许多非代码文件。目前这些都是图像,但将来我可能会使用其他类型的文件。存储和引用这些文件的好方案是什么?
我考虑在主目录中创建一个文件夹“resources”,但是有一个问题;一些图像是在我的项目的子包中使用的。以这种方式存储这些图像会导致耦合,这是一个缺点。
另外,我需要一种独立于当前目录的访问这些文件的方法。
I have a Python project in which I am using many non-code files. Currently these are all images, but I might use other kinds of files in the future. What would be a good scheme for storing and referencing these files?
I considered just making a folder "resources" in the main directory, but there is a problem; Some images are used from within sub-packages of my project. Storing these images that way would lead to coupling, which is a disadvantage.
Also, I need a way to access these files which is independent on what my current directory is.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可能需要使用
setuptools
附带的pkg_resources
库。例如,我制作了一个快速的小包
"proj"
来说明我将使用的资源组织方案:请注意我如何将所有资源保存在单独的子包中。
"code.py"
显示了如何使用pkg_resources
来引用资源对象:如果运行它,您会得到:
如果需要将资源视为文件对象,使用
resource_stream()
。访问资源的代码可能位于项目子包结构中的任何位置,在本例中,它只需要通过全名引用包含图像的子包:
proj.resources.images
。这是
“setup.py”
:警告:
要“本地”测试,即不首先安装软件包,您必须从包含
setup.py
的目录中调用测试脚本。如果您与code.py
位于同一目录中,Python 将不知道proj
包。因此像proj.resources
这样的事情将无法解决。You may want to use
pkg_resources
library that comes withsetuptools
.For example, I've made up a quick little package
"proj"
to illustrate the resource organization scheme I'd use:Notice how I keep all resources in a separate subpackage.
"code.py"
shows howpkg_resources
is used to refer to the resource objects:If you run it, you get:
If you need to treat a resource as a fileobject, use
resource_stream()
.The code accessing the resources may be anywhere within the subpackage structure of your project, it just needs to refer to subpackage containing the images by full name:
proj.resources.images
, in this case.Here's
"setup.py"
:Caveat:
To test things "locally", that is w/o installing the package first, you'll have to invoke your test scripts from directory that has
setup.py
. If you're in the same directory ascode.py
, Python won't know aboutproj
package. So things likeproj.resources
won't resolve.执行此操作的新方法是使用
importlib
。对于早于 3.7 的 Python 版本,您可以向importlib_resources
添加依赖项,并执行类似的操作:如果您的资源位于
foo/resources
子模块内,那么您将使用get_resource
像这样The new way of doing this is with
importlib
. For Python versions older than 3.7 you can add a dependency toimportlib_resources
and do something likeIf your resources live inside the
foo/resources
sub-module, you would then useget_resource
like so您始终可以在每个需要它的子包中拥有一个单独的“资源”文件夹,并使用 os.path 函数从子包的 __file__ 值中获取这些文件夹。为了说明我的意思,我在三个位置创建了以下
__init__.py
文件:这是
__init__.py
文件:在 c:\temp\work 中,我创建了一个app,topapp.py,如下:
这代表使用
topp
包和子包的应用程序。然后我运行它:正如预期的那样。我们设置 PYTHONPATH 来模拟将我们的包放在路径上:
如您所见,资源路径正确解析为路径上实际(子)包的位置。
更新: 这里是相关的 py2exe 文档。
You can always have a separate "resources" folder in each subpackage which needs it, and use
os.path
functions to get to these from the__file__
values of your subpackages. To illustrate what I mean, I created the following__init__.py
file in three locations:Here's the
__init__.py
file:In c:\temp\work, I create an app, topapp.py, as follows:
This respresents the application using the
topp
package and subpackages. Then I run it:That's as expected. We set the PYTHONPATH to simulate having our package on the path:
As you can see, the resource paths resolved correctly to the location of the actual (sub)packages on the path.
Update: Here's the relevant py2exe documentation.
@ pycon2009,有一个关于 distutils 和 setuptools 的演示。您可以在此处找到所有视频
Python 中的鸡蛋和构建部署 - 第 1 部分
Python 中的鸡蛋和构建部署 - 第 2 部分
Python 中的鸡蛋和构建部署 - 第 3 部分
在这些视频中,他们描述了如何在包中包含静态资源。我相信它在第 2 部分中。
使用 setuptools,您可以定义依赖项,这将允许您有 2 个包使用第 3 个包中的资源。
Setuptools 还为您提供了访问这些资源的标准方法,并允许您使用包内的相对路径,这样就无需担心包的安装位置。
@ pycon2009, there was a presentation on distutils and setuptools. You can find all of the videos here
Eggs and Buildout Deployment in Python - Part 1
Eggs and Buildout Deployment in Python - Part 2
Eggs and Buildout Deployment in Python - Part 3
In these videos, they describe how to include static resources in your package. I believe its in part 2.
With setuptools, you can define dependancies, this would allow you to have 2 packages that use resources from 3rd package.
Setuptools also gives you a standard way of accessing these resources and allows you to use relative paths inside of your packages, which eliminates the need to worry about where your packages are installed.