如何获取当前的“包"名称?(setup.py) [英] How do I get the current 'package' name? (setup.py)

查看:42
本文介绍了如何获取当前的“包"名称?(setup.py)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获取当前最顶层的包,即 setup.py 中定义的名称?

这是我的:

<预><代码>.|-- README.md|-- the_project_name_for_this_pkg||-- __init__.py||-- __main__.py||-- _config||`--foo.conf||-- _data||`--logging.yml|`-- 测试||-- __init__.py|`-- test_foo.py <--- # 从这里执行|-- 需求.txt`--setup.py4个目录,9个文件

到目前为止,我工作的唯一解决方案是:

导入操作系统导入系统os.path.basename(sys.path[1])

但这显然是一个糟糕的解决方案.其他解决方案,例如在我最上层的 __init__.py 文件中有一个 __name__ 并使用 ast.parse 阅读setup.py 的相关部分也显得很麻烦.

我尝试过的其他解决方案——通过在 unittest.TestCase 在我的tests python [sub]包中继承class——包括检查sys.modules[__name__], inspect.getmodule&inspect.stack,以及作为这些问题的答案:

顺便说一句:如果你想知道为什么我想要包名......这样我就可以运行:

import pkg_resourcesversion = pkg_resources.require('the_project_name_for_this_pkg')[0].versiondata_file = path.join(resource_filename('the_project_name_for_this_pkg', '__init__.py'),'_config', 'data_file.txt')

解决方案

不完全确定更大的目标是什么,但也许您可能有兴趣阅读 importlib.resources 以及 importlib.metadata.

类似于以下内容:

import importlib.metadata导入 importlib.resourcesversion = importlib.metadata.version('SomeProject')data = importlib.resources.files('top_level_package.sub_package').joinpath('file.txt').read_text()

更一般地说,从代码中 100% 可靠地检测项目的名称 (SomeProject) 几乎是不可能的(或不值得进行大量的工作).直接对其进行硬编码会更容易.

不过,这里有一些技术和想法,可以从其中一个模块中检索项目名称:


更新:

我相信像下面这样的函数应该返回包含当前文件的已安装发行版的名称:

导入路径库导入 importlib_metadatadef get_project_name():对于 importlib_metadata.distributions() 中的 dist:尝试:relative = pathlib.Path(__file__).relative_to(dist.locate_file(''))除了值错误:经过别的:如果在 dist.files 中相对:返回 dist.metadata['Name']返回无


更新(2021 年 2 月):

由于 importlib_metadata 中新添加的 packages_distributions() 函数,看起来这会变得更容易:

How do I get the current topmost package, i.e., the name defined in setup.py?

Here is my tree:

.
|-- README.md
|-- the_project_name_for_this_pkg
|   |-- __init__.py
|   |-- __main__.py
|   |-- _config
|   |   `-- foo.conf
|   |-- _data
|   |   `-- logging.yml
|   `-- tests
|       |-- __init__.py
|       `-- test_foo.py   <--- # executing from here
|-- requirements.txt
`-- setup.py

4 directories, 9 files

The only solution I've gotten to work so far is this:

import os
import sys


os.path.basename(sys.path[1])

But this is obviously a bad solution. Other solutions like having a __name__ in my uppermost __init__.py file and using ast.parse to read in the relevant section of setup.py also seems cumbersome.

Other solutions I've tried—by calling them within a unittest.TestCase inheriting class in my tests python [sub]package—include checking sys.modules[__name__], inspect.getmodule & inspect.stack, as well as the answers to these questions:

BTW: In case you were wondering why I want the package name… it's so I can run things like:

import pkg_resources


version   = pkg_resources.require('the_project_name_for_this_pkg')[0].version
data_file = path.join(resource_filename('the_project_name_for_this_pkg', '__init__.py'),
                      '_config', 'data_file.txt')

解决方案

Not entirely sure what the larger goal is, but maybe you could be interested in reading about importlib.resources as well as importlib.metadata.

Something like the following:

import importlib.metadata
import importlib.resources

version = importlib.metadata.version('SomeProject')
data = importlib.resources.files('top_level_package.sub_package').joinpath('file.txt').read_text()

And more generally, it is near impossible (or not worth the amount of work) to 100% reliably detect the name of the project (SomeProject) from within the code. It is easier to just hard-code it.

Nevertheless here are some techniques, and ideas to retrieve the name of the project from one of its modules:


Update:

I believe some function like the following should return the name of the installed distribution containing the current file:

import pathlib
import importlib_metadata

def get_project_name():
    for dist in importlib_metadata.distributions():
        try:
            relative = pathlib.Path(__file__).relative_to(dist.locate_file(''))
        except ValueError:
            pass
        else:
            if relative in dist.files:
                return dist.metadata['Name']
    return None


Update (February 2021):

Looks like this could become easier thanks to the newly added packages_distributions() function in importlib_metadata:

这篇关于如何获取当前的“包"名称?(setup.py)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆