Pytanie Jak uzyskać dostęp do metadanych pakietu Pythona z poziomu konsoli Pythona?


Jeśli zbudowałem pakiet Pythona za pomocą distutils.core, np. przez

setup(
    ext_package="foo",
    author="me",
    version="1.0",
    description="foo package",
    packages=["foo",],
)

gdzie się znajdują wszystkie metadane (do czego jest przeznaczony?) i jak mogę uzyskać do niego dostęp z poziomu Pythona. W szczególności, w jaki sposób uzyskać dostęp do informacji o autorach z konsoli Pythona po wykonaniu czegoś podobnego

>>> import foo

11
2017-12-19 13:32


pochodzenie




Odpowiedzi:


Jednym ze sposobów uzyskania dostępu do metadanych jest użycie :

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.

lub pkg_resources

from pkg_resources import get_distribution

pkg = get_distribution('package_name')  # also contains a metadata

5
2017-12-19 13:47



Niestety nie mam pip zainstalowane teraz, więc nie można go przetestować. The pkg_resources.get_distribution podejście wydaje się nie działać dla rozszerzenia, które zostało zainstalowane za pomocą prostego python setup.py build. W tym przypadku dostaję DistributionNotFound: foo wyjątek. - dastrobu
python setup.py nie instaluje się. - Éric Araujo
Zastosowanie pip dodaje ogromne opóźnienie w czasie importowania i dodaje znaczny ślad pamięci do twojego własnego kodu. To wewnętrznie po prostu używa pkg_resources i daje ci identyczny rezultat; gruntownie, pip tutaj jest nieistotne i mylące "rozwiązanie". Odpowiedź również nie dostarcza właściwie pożądanych informacji; od Distribution obiekt jest bardzo nieoczywisty, jak uzyskać wersję, autora i opis, wśród innych pól, z powrotem. pkg._get_metadata(pkg.PKG_INFO) pobiera poszczególne linie z pliku metadanych jako listę, na początek. - amcgregor


Metadane są przechowywane wewnątrz <package>-<version>-<py version>.egg-info plik.

podczas tworzenia modułu powinieneś mieć następujący wiersz:

Writing /usr/lib/python2.7/site-packages/foobar-1.0-py2.7.egg-info

Ten plik zawiera metadane:

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

Jeśli chcesz uzyskać do niego dostęp, najlepszym sposobem jest pip lub pkg_resources (jak powiedział Alexander Zhukov) np .:

>>> import pkg_resources
>>> d = pkg_resources.get_distribution('Foobar')
>>> d.version
'1.0'
>>> d.location
'/usr/lib/python2.7/site-packages'

3
2017-12-19 14:11



Brakuje wymaganego kroku, aby rzeczywiście odczytać metadane: d._get_metadata(d.PKG_INFO)  Nieuzbrojony obiekt dystrybucyjny nie ma szczególnie oczywistego sposobu dostępu do informacji. - amcgregor


Jednym z zastosowań tych danych jest to, że jest wyświetlany na Pypi (http://pypi.python.org/), jeśli opublikujesz tam swój pakiet. Jednym ze sposobów jego struktury jest:

na najwyższym poziomie twojego foo moduł:

__author__= "me"
__version__= "1.0"
__description__= "foo package"

w setup.py:

import foo
setup(

    author = foo.__author__,
    version = foo.__version__,
    description = foo.__description__,
    packages = ["foo",],

)

W ten sposób wystarczy zaktualizować swoje metadane w jednym miejscu, a ponieważ dane są zdefiniowane w głównym module pakietów, będzie on dostępny z tego miejsca.


1
2017-12-19 14:17



Tu jest niezwykle ważny catch-22. Twój skrypt instalacyjny zależy teraz od tego, czy instalowany pakiet jest już zainstalowany (lub przynajmniej już można go importować). To nie jest dobra rzecz. (Głosowanie w dół za potencjalnie niebezpieczną praktykę.) - amcgregor


Dany setup.py następująco:

from distutils.core import setup

setup(
    name         = 'TestApp',
    version      = '0.0.1',
    author       = 'saaj',
    py_modules   = ['app'],
    test_suite   = 'test'
)

Dla niektórych skryptów i automatyzacji bez instalowania pakietu, gdzie pip, easy_install i nawet setuptools nie udostępniaj opcji wiersza poleceń ani publicznych interfejsów API do czytania wszystkich metadanych (np. test_suite), oto trochę hackowy sposób:

python3 -c "import sys, types; m = types.ModuleType('distutils.core'); \
    m.setup = lambda **kwargs: print(kwargs); \
    sys.modules['distutils.core'] = m; import setup" 

Spowoduje to wydrukowanie a dict słów kluczowych przekazanych do setup().

{'author': 'saaj', 'version': '0.0.1', 'name': 'TestApp', 
    'test_suite': 'test', 'py_modules': ['app']}

Możesz wymienić print w lambda do dowolnego wyjścia, którego potrzebujesz. Jeżeli twój setup.py import setup() od setuptools, co jest w rzeczywistości polecanym sposobem, po prostu zamień "distutils.core" na "setuptools" we fragmencie.

Sformatowany fragment kodu:

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()

0
2017-11-30 09:49