"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의 일부는 아닙니다. 메타 데이터 내용에 액세스하려면,
    딕셔너리와 같은 메서드와 문법을 사용해야 합니다.
