Если я создал пакет python с использованием distutils.core
, например. с помощью
setup(
ext_package="foo",
author="me",
version="1.0",
description="foo package",
packages=["foo",],
)
где все метаданные идут (для чего это предназначено?) и как я могу получить к нему доступ изнутри python. В частности, как я могу получить доступ к информации об авторе с консоли python после выполнения чего-то вроде
>>> import foo
Ответ 1
Один из способов доступа к метаданным - использовать 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
Ответ 2
Метаданные хранятся внутри файла <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: foobar@foobar.net
License: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
Если вы хотите получить к нему доступ, лучший способ - pip
или pkg_resources
(как сказал Александр Жуков)
ex:
>>> import pkg_resources
>>> d = pkg_resources.get_distribution('Foobar')
>>> d.version
'1.0'
>>> d.location
'/usr/lib/python2.7/site-packages'
Ответ 3
Что касается только метаданных version
, я нашел довольно ненадежным использование различных доступных инструментов, поскольку большинство из них не охватывает все случаи. Например
- встроенные модули
- модули не установлены, а просто добавлены в путь к Python (например, вашей IDE)
- доступны две версии одного и того же модуля (одна в пути Python заменяет установленную)
Так как нам нужен был надежный способ получить версию любого пакета, модуля или субмодуля, я закончил писать getversion. Это довольно просто использовать:
from getversion import get_module_version
import foo
version, details = get_module_version(foo)
Смотрите документацию для деталей.
Ответ 4
Одно использование этих данных состоит в том, что оно отображается на Pypi (http://pypi.python.org/), если вы собираетесь опубликовать там свой пакет. Один из способов его структурирования выглядит так:
на верхнем уровне вашего модуля 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",],
)
Таким образом вам нужно только обновить метаданные в одном месте, а так как данные определены в главном модуле пакетов, он будет доступен оттуда.
Ответ 5
Учитывая 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
), здесь немного хакерский путь:
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()
Ответ 6
С python3.8 за углом вы можете использовать новый модуль importlib.metadata
для анализа метаданных любого установленного пакета.
Получение информации об авторе будет выглядеть так:
>>> from importlib import metadata
>>> metadata.metadata('foo')['Author']
'me'
Что намного проще, чем прежние способы.