# `importlib.metadata` 사용하기

Source code: Lib/importlib/metadata.py

버전 3.8에 추가.

참고

이 기능은 잠정적이며 표준 라이브러리의 일반적인 버전 의미와 다를 수 있습니다.

`importlib.metadata`는 설치된 패키지 메타 데이터에 대한 액세스를 제공하는 라이브러리입니다. 파이썬의 임포트 시스템에 내장된 이 라이브러리는 `pkg_resources`의 진입 지점 API와 메타데이터 API에서 유사한 기능을 대체하려고 합니다. 파이썬 3.7 이상의 `importlib.resources`(이전 버전의 파이썬을 위해 importlib_resources로 역 이식되었습니다)와 함께, 오래되고 덜 효율적인 `pkg_resources` 패키지를 사용할 필요를 제거합니다.

“설치된 패키지”는 일반적으로 pip 와 같은 도구를 통해 파이썬의 `site-packages` 디렉터리에 설치된 제삼자 패키지를 의미합니다. 특히, 발견 가능한 `dist-info`나 `egg-info` 디렉터리와 PEP 566 또는 이전 명세로 정의된 메타 데이터가 있는 패키지를 의미합니다. 기본적으로, 패키지 메타 데이터는 파일 시스템이나 `sys.path`의 zip 저장소에서 살 수 있습니다. 확장 메커니즘을 통해, 메타 데이터는 거의 모든 곳에서 살아갈 수 있습니다.

## 개요

`pip`를 사용하여 설치한 패키지의 버전 문자열을 얻고 싶다고 가정해 봅시다. 우선 가상 환경을 만들고 그 안에 뭔가 설치합니다:

    $ python3 -m venv example
    $ source example/bin/activate
    (example) $ pip install wheel

다음을 실행하여 `wheel`에 대한 버전 문자열을 얻을 수 있습니다:

    (example) $ python
    >>> from importlib.metadata import version
    >>> version('wheel')
    '0.32.3'

`console_scripts`, `distutils.commands`와 다른 것들과 같은 그룹 키로 진입 지점 집합을 얻을 수도 있습니다. 각 그룹은 EntryPoint 객체의 시퀀스를 포함합니다.

여러분은 배포 메타데이터를 얻을 수 있습니다:

    >>> list(metadata('wheel'))
    ['Metadata-Version', 'Name', 'Version', 'Summary', 'Home-page', 'Author', 'Author-email', 'Maintainer', 'Maintainer-email', 'License', 'Project-URL', 'Project-URL', 'Project-URL', 'Keywords', 'Platform', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Requires-Python', 'Provides-Extra', 'Requires-Dist', 'Requires-Dist']

또한 배포의 버전 번호를 가져오고, 구성 파일을 나열하고, 배포의 배포 요구 사항 리스트를 얻을 수 있습니다.

## 기능적 API

이 패키지는 공용 API를 통해 다음과 같은 기능을 제공합니다.

### 진입 지점

`entry_points()` 함수는 그룹 키를 갖는 모든 진입 지점의 딕셔너리를 반환합니다. 진입 지점은 `EntryPoint` 인스턴스로 나타냅니다; 각 `EntryPoint`에는 `.name`, `.group` 및 `.value` 어트리뷰트가 있고 값을 결정하는 `.load()` 메서드가 있습니다. `.value` 어트리뷰트의 구성 요소를 가져오기 위한 `.module`, `.attr` 및 `.extras` 어트리뷰트도 있습니다:

    >>> eps = entry_points()
    >>> list(eps)
    ['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation']
    >>> scripts = eps['console_scripts']
    >>> wheel = [ep for ep in scripts if ep.name == 'wheel'][0]
    >>> wheel
    EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')
    >>> wheel.module
    'wheel.cli'
    >>> wheel.attr
    'main'
    >>> wheel.extras
    []
    >>> main = wheel.load()
    >>> main
    <function main at 0x103528488>

`group`과 `name`은 패키지 저자가 정의한 임의의 값이며 일반적으로 클라이언트는 특정 그룹에 대한 모든 진입 지점을 찾으려고 합니다. 진입 지점의 정의와 사용법에 대한 자세한 정보는 the setuptools docs를 읽으십시오.

### 배포 메타데이터

모든 배포는 `metadata()` 함수를 사용하여 추출할 수 있는 몇 가지 메타 데이터가 포함되어 있습니다:

    >>> wheel_metadata = metadata('wheel')

반환된 데이터 구조의 1 키는 메타데이터 키워드의 이름을 지정하고, 해당 값은 배포 메타데이터에서 구문 분석하지 않은 채로 반환됩니다:

    >>> wheel_metadata['Requires-Python']
    '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'

### 배포 버전

`version()` 함수는 배포의 버전 번호를 문자열로 가져오는 가장 빠른 방법입니다:

    >>> version('wheel')
    '0.32.3'

### 배포 파일

You can also get the full set of files contained within a distribution. The `files()` function takes a distribution package name and returns all of the files installed by this distribution. Each file object returned is a `PackagePath`, a `pathlib.PurePath` derived object with additional `dist`, `size`, and `hash` properties as indicated by the metadata. For example:

    >>> util = [p for p in files('wheel') if 'util.py' in str(p)][0]
    >>> util
    PackagePath('wheel/util.py')
    >>> util.size
    859
    >>> util.dist
    <importlib.metadata._hooks.PathDistribution object at 0x101e0cef0>
    >>> util.hash
    <FileHash mode: sha256 value: bYkw5oMccfazVCoYQwKkkemoVyMAFoR34mmKBx8R1NI>

일단 파일을 얻으면, 내용을 읽을 수도 있습니다:

    >>> print(util.read_text())
    import base64
    import sys
    ...
    def as_bytes(s):
        if isinstance(s, text_type):
            return s.encode('utf-8')
        return s

You can also use the `locate` method to get a the absolute path to the file:

    >>> util.locate()
    PosixPath('/home/gustav/example/lib/site-packages/wheel/util.py')

메타 데이터 파일 목록 파일(RECORD나 SOURCES.txt)이 누락된 경우, `files()`는 `None`을 반환합니다. 대상 배포에 메타 데이터가 있음이 알려지지 않았을 때, 이 조건에 대한 보호로 호출자는 `files()`에 대한 호출을 always_iterable이나 다른 것으로 감쌀 수 있습니다.

### 배포 요구 사항

배포의 전체 요구 사항을 얻으려면, `requires()` 함수를 사용하십시오:

    >>> requires('wheel')
    ["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]

## 배포

위의 API가 가장 일반적이며 편리한 사용법이지만, `Distribution` 클래스에서 모든 정보를 얻을 수 있습니다. `Distribution`은 파이썬 패키지의 메타 데이터를 나타내는 추상 객체입니다. `Distribution` 인스턴스를 얻을 수 있습니다:

    >>> from importlib.metadata import distribution
    >>> dist = distribution('wheel')

따라서, 버전 번호를 얻는 다른 방법은 `Distribution` 인스턴스를 사용하는 것입니다:

    >>> dist.version
    '0.32.3'

`Distribution` 인스턴스에서 사용할 수 있는 모든 종류의 추가 메타 데이터가 있습니다:

    >>> dist.metadata['Requires-Python']
    '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
    >>> dist.metadata['License']
    'MIT'

사용 가능한 메타 데이터의 전체 집합은 여기에서 설명하지 않습니다. 자세한 내용은 PEP 566을 참조하십시오.

## 검색 알고리즘 확장하기

패키지 메타 데이터는 `sys.path` 검색이나 패키지 로더를 통해 직접 사용할 수 없으므로, 패키지의 메타 데이터는 임포트 시스템 파인더를 통해 찾습니다. 배포 패키지의 메타 데이터를 찾기 위해, `importlib.metadata`는 `sys.meta_path`의 메타 경로 파인더의 리스트를 조회합니다.

파이썬의 기본 `PathFinder`에는 일반적인 파일 시스템 기반 경로에서 로드된 배포를 찾기 위해 `importlib.metadata.MetadataPathFinder`를 호출하는 훅이 포함되어 있습니다.

추상 클래스 `importlib.abc.MetaPathFinder`는 파이썬의 임포트 시스템에 의해 파인더가 기대하는 인터페이스를 정의합니다. `importlib.metadata`는 `sys.meta_path`의 파인더에서 선택적인 `find_distributions` 콜러블을 조회함으로써 이 프로토콜을 확장하고 이 확장된 인터페이스를 다음과 같은 추상 메서드를 정의하는 `DistributionFinder` 추상 베이스 클래스로 제공합니다:

    @abc.abstractmethod
    def find_distributions(context=DistributionFinder.Context()):
        """Return an iterable of all Distribution instances capable of
        loading the metadata for packages for the indicated ``context``.
        """

`DistributionFinder.Context` 객체는 검색할 경로와 일치할 이름을 가리키는 `.path`와 `.name` 프로퍼티를 제공하고 다른 관련 문맥을 제공할 수 있습니다.

이것이 실제로 의미하는 것은, 파일 시스템이 아닌 위치에서 배포 패키지 메타 데이터를 찾는 것을 지원하려면, `Distribution`을 서브 클래싱하고 추상 메서드를 구현해야 한다는 것입니다. 그런 다음 사용자 정의 파인더의 `find_distributions()` 메서드에서, 이 파생된 `Distribution`의 인스턴스를 반환하십시오.

각주

1

  기술적으로, 반환된 배포 메타 데이터 객체는 `email.message.EmailMessage` 인스턴스이지만, 이것은 구현 세부 사항이며 안정 API의 일부는 아닙니다. 메타 데이터 내용에 액세스하려면, 딕셔너리와 같은 메서드와 문법을 사용해야 합니다.