【问题标题】:Get Path to Subpackage in Python在 Python 中获取子包的路径
【发布时间】:2020-08-19 02:14:16
【问题描述】:

我有一个项目需要从 python2 更新到 python3。它目前使用pkg_resources,它有很大的开销(PyCon 2018 - Get Your Resources Faster with importlib.resources, by Barry Warsaw)。它将被打包成一个 zip 文件。包结构的相关部分是:

+-- project/
|__+ __init__.py
|__+ main.py
|__resources/
|  |__+ images/
|  |  |__ # program images
|  |__+ logging/
|     |__+ custom_logger.py
|__log/
   |__+ project_log.log

原始问题的意图

最初问题的目的是询问“如何从另一个子包中获取子包的绝对路径”,但我在措辞上做得很差。我认为由于current working directory 的意思是“运行cwd 命令的路径”,所以可以使用它,但后来我了解到我的理解是不完整的。 current working directory 表示(用外行的话)“从在命令行 运行cwd 命令的路径”)。这就是我遇到麻烦的原因。如果我从顶级包中运行我的程序

C:\Users\usr\Destop\program>py main.py

并在任何其他子包(resourceslogginglog)中的.py 文件中使用pathlib.Path.cwd(),我会得到相同的答案:

C:\Users\usr\Destop\program

我了解到这是正确的行为,但这意味着我不能使用相对路径从一个子包到另一个子包(我需要使用相对路径,因为我不知道最终用户将在他/她的哪里安装此程序机器)。

与未明确说明的问题相关的第二部分

由于我的部分需求是更新到 python3,因此对 pkgutilimportlib.resources 进行了调查。其中每一个都需要将资源视为包,因此要更新以使用其中任何一个,我必须将__init__.py 添加到文件夹resourceslogginglog。谢天谢地,这没什么大不了的,因为这不是一个大型程序。

请注意,为了向后兼容最少的代码重新编辑,已建议其他人使用命名空间重命名(例如,请参阅 (How to use importlib.resources.path(package, resource)?)。:

try:
    import importlib.resources as pkg_resources
except ImportError:
    # Try backported to PY<37 `importlib_resources`.
    import importlib_resources as pkg_resources

pgkutilimportlib.resources 都没有直接返回“这个子包”的方法(就像pathlib.Path.cwd()“直接返回”cwd 没有任何额外的代码),但我认为importlib.resources 有一种我可以使用的方法,它需要最少的代码并且读者仍然可以理解。请注意,要求是获取“此子包”的绝对路径,仅此而已。我不想使用不同的方法。

我会使用的方法是

try:
    import importlib.resources as pkg_resources
except ImportError:
    # Try backported to PY<37 `importlib_resources`.
    import importlib_resources as pkg_resources

with pkg_resources.path("logging", "__init__.py") as fl:
    path = fl.parent.resolve()

结论

除此之外,我没有任何问题,因为它可能会被判断为“意见”问题。请注意 __file__ 方法是不可接受的,因为这不适用于 zip 包(请参阅 PyCon 2018 - Get Your Resources Faster with importlib.resources, by Barry Warsaw)。如果这种方法有什么不正确或者可以改进的地方,我想知道。

【问题讨论】:

  • 在这两种情况下,您都希望答案是“项目”吗?我认为这可能需要了解目录结构的嵌套程度。
  • @mk03 我对你的意思感到困惑。你是在谈论Path.cwd() 返回的内容吗?
  • 我想问你想要的输出是什么?
  • 所需的输出将是文件的绝对路径。为此,我可能需要更改为 cwd = str(fl.parent.resolve())

标签: python-3.7 working-directory pathlib python-importlib


【解决方案1】:

任何 python 文件都可以通过 file 访问它自己的位置。因此,例如,您可以简单地做

pathlib.Path(__file__).parent 

访问运行该代码的文件的目录。这与您运行程序的位置和/或安装程序的位置无关。

【讨论】:

  • 这不适用于 zip 文件中包含的代码。 (可能在创建 .eggs 或打包上传到 PyPI 时发生)
  • 投反对票的奇怪理由。我不记得OP提到的zip文件。另外,您刚刚在 setup.py 中将 zip 标志设置为不安全吗?
  • 没错,您可以将zip_safe设置为False。很抱歉投票失败。这样做只是为了改进答案,因为这并非在所有情况下都有效。
  • 对,但同样,这甚至不是 OP 问题的一部分。
  • 不,__file__ 不能被 importlib 使用。这被认为是不好的做法。请观看 Barry Warsaw 的 PyCon 2018 视频“使用 importlib.resources 更快地获取资源”youtube.com/watch?v=ZsGFU2qh73E>。
猜你喜欢
  • 2022-01-03
  • 2011-08-30
  • 1970-01-01
  • 2016-01-17
  • 2017-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-26
相关资源
最近更新 更多