如果我构建了一个使用
distutils.core
的 python 包,例如通过
setup(
ext_package="foo",
author="me",
version="1.0",
description="foo package",
packages=["foo",],
)
所有元数据都去哪里了(它的用途是什么?)以及我如何从 python 中访问它。具体来说,在执行类似
的操作后,如何从 python 控制台访问作者信息>>> import foo
importlib.metadata
[1] 模块来解析任何已安装包的元数据。
获取作者信息如下所示:
>>> from importlib import metadata
>>> metadata.metadata('foo')['Author'] # let's say you called your package 'foo'
'Arne'
获取安装版本:
>>> from importlib import metadata
>>> metadata.version('foo')
'0.1.0'
这比你以前必须做的要简单得多。
[1] 也可作为 Python2.7 和 3.5+ 的后向端口作为 importlib-metadata,感谢@ChrisHunt 指出这一点。
访问元数据的一种方法是使用pip:
import pip
package = [pckg for pckg in pip.get_installed_distributions()
if pckg.project_name == 'package_name'][0]
# package var will contain some metadata: version, project_name and others.
或
pkg_resources
from pkg_resources import get_distribution
pkg = get_distribution('package_name') # also contains a metadata
元数据存储在
<package>-<version>-<py version>.egg-info
文件中。
当你创建你的模块时,你应该有这一行:
Writing /usr/lib/python2.7/site-packages/foobar-1.0-py2.7.egg-info
此文件包含元数据:
Metadata-Version: 1.0
Name: Foobar
Version: 1.0
Summary: foobar
Home-page: http://foobar.com/
Author: foobar
Author-email: [email protected]
License: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
如果你想访问它,最好的方法是使用
pip
或 pkg_resources
(如 Alexander Zhukov 所说)
例如:
>>> import pkg_resources
>>> d = pkg_resources.get_distribution('Foobar')
>>> d.version
'1.0'
>>> d.location
'/usr/lib/python2.7/site-packages'
仅关于
version
元数据,我发现使用各种可用的工具非常不可靠,因为它们中的大多数都不能涵盖所有情况。例如
由于我们需要一种可靠的方法来获取 any 包、模块或子模块的版本,所以我最终编写了 getversion。使用起来非常简单:
from getversion import get_module_version
import foo
version, details = get_module_version(foo)
有关详细信息,请参阅文档。
虽然我更喜欢使用
importlib.metadata
,因为已经有另一个答案展示了如何做到这一点,我会告诉你另一种选择。
genespeak
来自 PyPI。
metadata
try:
from importlib import metadata
except ImportError: # for Python<3.8
import importlib_metadata as metadata
print(metadata.name('genespeak')) # genespeak
print(metadata.version('genespeak')) # 0.0.7
pkginfo
PyPI我们将使用以下5种方式获取包裹信息。
from pkginfo import SDist, BDist, Wheel, Installed, Develop
通常您会创建源分发文件:
python setup.py sdist
假设您在路径中有一个
.tar.gz
文件:./dist/genespeak-0.0.7.tar.gz
,这是您需要提取包信息的内容。
from pkginfo import SDist
pkg = SDist("./dist/genespeak-0.0.7.tar.gz")
# Now you can access the metadata fields from
# PKG-INFO file inside the source file:
# `./dist/genespeak-0.0.7.tar.gz`
print(pkg.name) # genespeak
print(pkg.version) # 0.0.7
通常你会创建二进制分发文件(
.egg
):
python setup.py bdist_egg
假设您在路径中有一个
.egg
文件:./dist/genespeak-0.0.7-py38.egg
,这是您需要提取包信息的内容。
from pkginfo import BDist
pkg = BDist("./dist/genespeak-0.0.7-py38.egg")
# Now you can access the metadata fields from
# the binary distribution file (*.egg):
# `./dist/genespeak-0.0.7-py38.egg`
print(pkg.name) # genespeak
print(pkg.version) # 0.0.7
通常你会创建二进制分发轮文件(
.whl
):
python setup.py bdist_wheel
假设您在路径中有一个
.whl
文件:./dist/genespeak-0.0.7-py3-none-any-whl
,这是您需要提取包信息的内容。
from pkginfo import Wheel
pkg = Wheel("./dist/genespeak-0.0.7-py3-none-any-whl")
# Now you can access the metadata fields from
# PKG-INFO file inside the source file:
# `./dist/genespeak-0.0.7-py3-none-any.whl`
print(pkg.name) # genespeak
print(pkg.version) # 0.0.7
查看这里了解更多详情
from pkginfo import Installed
import genespeak
pkg = Installed(genespeak)
# Now you can access the metadata fields from
# PKG-INFO file inside the source file:
# `./dist/genespeak-0.0.7.tar.gz`
print(pkg.name) # genespeak
print(pkg.version) # 0.0.7
from pkginfo import Develop
dev = Develop(".")
# Now you can access the metadata fields from
# PKG-INFO file under `genespeak.egg-info`
# directory under the project root.
print(dev.name) # genespeak
print(dev.version) # 0.0.7
pkginfo
文件鉴于
setup.py
如下:
from distutils.core import setup
setup(
name = 'TestApp',
version = '0.0.1',
author = 'saaj',
py_modules = ['app'],
test_suite = 'test'
)
对于一些没有安装包的脚本和自动化,其中
pip
、easy_install
甚至 setuptools
不提供命令行选项或公共 API 来读取所有元数据(例如 test_suite
),这里有一些 hacky 方式:
python3 -c "import sys, types; m = types.ModuleType('distutils.core'); \
m.setup = lambda **kwargs: print(kwargs); \
sys.modules['distutils.core'] = m; import setup"
这将打印传递给
dict
的关键字参数的setup()
。
{'author': 'saaj', 'version': '0.0.1', 'name': 'TestApp',
'test_suite': 'test', 'py_modules': ['app']}
您可以将
print
中的lambda
替换为您需要的任何输出。如果您的setup.py
从setup()
导入setuptools
,这实际上是推荐的方式,只需在代码段中将“distutils.core”替换为“setuptools”。
格式化片段如下:
import sys
import types
m = types.ModuleType('distutils.core')
m.setup = lambda **kwargs: print(kwargs)
sys.modules['distutils.core'] = m
import setup # import you setup.py with mocked setup()
此数据的一个用途是,如果您要在 Pypi (http://pypi.python.org/) 上发布您的包,它就会显示在 Pypi 上。一种构造它的方法是这样的:
在您的
foo
模块的顶层:
__author__= "me"
__version__= "1.0"
__description__= "foo package"
在
setup.py
:
import foo
setup(
author = foo.__author__,
version = foo.__version__,
description = foo.__description__,
packages = ["foo",],
)
这样你只需要在一个地方更新你的元数据,因为数据是在你的包主模块中定义的,所以可以从那里访问它。