6. Distutils 예제

참고

이 문서는 https://setuptools.readthedocs.io/en/latest/setuptools.htmlsetuptools 설명서가 현재 여기에 포함된 모든 관련 정보를 독립적으로 다루기 전까지만 보존됩니다.

이 장에서는 distutils를 시작하는 데 도움이 되는 여러 가지 기본 예를 제공합니다. distutils 사용에 대한 추가 정보는 Distutils Cookbook에서 찾을 수 있습니다.

더 보기

Distutils Cookbook

distutils를 더 잘 제어하는 방법을 보여주는 조리법 모음.

6.1. 순수한 파이썬 배포 (모듈별)

단지 몇 개의 모듈만 배포한다면, 특히 특정 패키지에 속하지 않는 모듈이면, 설정 스크립트에서 py_modules 옵션을 사용하여 개별적으로 지정할 수 있습니다.

가장 간단한 경우, 두 가지 파일을 염두에 두어야 합니다: 설정 스크립트와 배포 할 단일 모듈, 이 예에서는 foo.py:

<root>/
        setup.py
        foo.py

(이 섹션의 모든 다이어그램에서 <root>는 배포 루트 디렉터리를 가리킵니다.) 이 상황을 설명하기 위한 최소 설정 스크립트는 다음과 같습니다:

from distutils.core import setup
setup(name='foo',
      version='1.0',
      py_modules=['foo'],
      )

배포판의 이름은 name 옵션으로 독립적으로 지정되며, 배포판의 유일한 모듈 이름과 같아야 한다는 규칙은 없습니다 (아마도 따라야 할 좋은 규칙임에도 불구하고). 그러나 배포판 이름은 파일명을 생성하는 데 사용되어서, 글자, 숫자, 밑줄 및 하이픈만 사용해야 합니다.

py_modules는 리스트이므로, 여러 모듈을 지정할 수 있습니다, 예를 들어 foobar 모듈을 배포한다면, 설정은 다음과 같습니다:

<root>/
        setup.py
        foo.py
        bar.py

그리고 설정 스크립트는 이렇습니다

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      py_modules=['foo', 'bar'],
      )

모듈 소스 파일을 다른 디렉터리에 넣을 수 있지만, 그렇게 할 모듈이 아주 많다면, 개별적으로 나열하지 않고 패키지로 모듈을 지정하기가 아마도 더 쉽습니다.

6.2. 순수한 파이썬 배포 (패키지별)

배포할 모듈이 많으면, 특히 여러 패키지에 있다면, 개별 모듈보다는 전체 패키지를 지정하기가 아마도 더 쉽습니다. 모듈이 패키지에 없는 경우에도 작동합니다; 루트 패키지에서 모듈을 처리하도록 Distutils에 지시 할 수 있으며, 다른 패키지와 동일하게 작동합니다 (__init__.py 파일이 필요하지 않다는 것만 다릅니다).

마지막 예제의 설정 스크립트는 다음과 같이 작성할 수도 있습니다

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      packages=[''],
      )

(빈 문자열은 루트 패키지를 나타냅니다.)

이 두 파일이 하위 디렉터리로 이동했지만, 루트 패키지에 남아있다면, 예를 들어:

<root>/
        setup.py
        src/      foo.py
                  bar.py

그러면 여전히 루트 패키지를 지정하지만, 루트 패키지의 소스 파일이 어디에 있는지 Distutils에 알려야 합니다:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      package_dir={'': 'src'},
      packages=[''],
      )

그러나 더 일반적으로는, 같은 패키지(또는 서브 패키지)에 있는 여러 모듈을 배포하고자 합니다. 예를 들어, foobar 모듈이 패키지 foobar에 속하면, 소스 트리를 배치하는 한 가지 방법은 다음과 같습니다:

<root>/
        setup.py
        foobar/
                 __init__.py
                 foo.py
                 bar.py

이것은 사실 Distutils가 예상하는 기본 배치이며, 설정 스크립트에서 설명할 작업이 가장 적은 배치입니다:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      packages=['foobar'],
      )

패키지 이름으로 지정되지 않은 디렉터리에 모듈을 넣으려면, package_dir 옵션을 다시 사용해야 합니다. 예를 들어, src 디렉터리에 foobar 패키지의 모듈이 있다면:

<root>/
        setup.py
        src/
                 __init__.py
                 foo.py
                 bar.py

적절한 설정 스크립트는 다음과 같습니다

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      package_dir={'foobar': 'src'},
      packages=['foobar'],
      )

또는, 메인 패키지의 모듈을 배포 루트에 바로 넣을 수 있습니다:

<root>/
        setup.py
        __init__.py
        foo.py
        bar.py

이 경우 설정 스크립트는 다음과 같습니다

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      package_dir={'foobar': ''},
      packages=['foobar'],
      )

(빈 문자열은 현재 디렉터리를 나타냅니다.)

서브 패키지가 있으면, packages에 명시적으로 나열되어야 하지만, package_dir의 모든 항목은 서브 패키지로 자동 확장됩니다. (즉, Distutils는 __init__.py 파일을 찾아서 어떤 디렉터리가 파이썬 패키지에 해당하는지 파악하려고 시도하면서 소스 트리를 스캔하지 않습니다.) 따라서, 기본 배치가 서브 패키지로 뻗어 나가는 경우:

<root>/
        setup.py
        foobar/
                 __init__.py
                 foo.py
                 bar.py
                 subfoo/
                           __init__.py
                           blah.py

해당 설정 스크립트는 이렇게 됩니다

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      packages=['foobar', 'foobar.subfoo'],
      )

6.3. 단일 확장 모듈

확장 모듈은 ext_modules 옵션을 사용하여 지정됩니다. package_dir은 확장 소스 파일이 있는 위치를 찾는 데 영향을 미치지 않습니다; 순수한 파이썬 모듈의 소스에만 영향을 미칩니다. 단일 C 소스 파일에 단일 확장 모듈이 들어 있는, 가장 간단한 경우는 이렇습니다:

<root>/
        setup.py
        foo.c

foo 확장이 루트 패키지에 속하면, 이를 위한 설정 스크립트는 다음과 같습니다

from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[Extension('foo', ['foo.c'])],
      )

확장이 실제로 패키지에 속하면, 가령 foopkg

정확히 같은 소스 트리 배치로, 간단히 확장의 이름을 변경하여 이 확장을 foopkg 패키지에 넣을 수 있습니다:

from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[Extension('foopkg.foo', ['foo.c'])],
      )

6.4. 패키지 검사하기

check 명령을 사용하면 패키지 메타 데이터가 배포판을 빌드하기 위한 최소 요구 사항을 충족하는지 확인할 수 있습니다.

실행하려면, setup.py 스크립트를 사용하여 호출하십시오. 뭔가 빠진 것이 있으면, check는 경고를 표시합니다.

간단한 스크립트로 예를 들어 봅시다:

from distutils.core import setup

setup(name='foobar')

check 명령을 실행하면 몇 가지 경고가 표시됩니다:

$ python setup.py check
running check
warning: check: missing required meta-data: version, url
warning: check: missing meta-data: either (author and author_email) or
         (maintainer and maintainer_email) should be supplied

long_description 필드에 reStructuredText 문법을 사용하고 docutils가 설치되었으면 restructuredtext 옵션을 사용하여 check 명령으로 문법이 올바른지 확인할 수 있습니다.

예를 들어, setup.py 스크립트가 다음과 같이 변경되면:

from distutils.core import setup

desc = """\
My description
==============

This is the description of the ``foobar`` package.
"""

setup(name='foobar', version='1', author='tarek',
    author_email='tarek@ziade.org',
    url='http://example.com', long_description=desc)

긴 설명이 망가지면, checkdocutils 구문 분석기를 사용하여 이를 감지할 수 있습니다:

$ python setup.py check --restructuredtext
running check
warning: check: Title underline too short. (line 2)
warning: check: Could not finish the parsing.

6.5. 메타 데이터 읽기

distutils.core.setup() 함수는 주어진 프로젝트의 setup.py 스크립트를 통해 프로젝트의 메타 데이터 필드를 조회할 수 있는 명령 줄 인터페이스를 제공합니다:

$ python setup.py --name
distribute

이 호출은 distutils.core.setup() 함수를 실행하여 name 메타 데이터를 읽습니다. Distutils로 소스나 바이너리 배포판이 만들어질 때, 메타 데이터 필드는 PKG-INFO라는 정적 파일에 기록됩니다. Distutils 기반 프로젝트가 파이썬에 설치되면, PKG-INFO 파일은 배포판의 모듈과 패키지와 함께 NAME-VERSION-pyX.X.egg-info 밑에 복사됩니다, 여기서 NAME은 프로젝트 이름, VERSION은 메타 데이터에 정의된 버전, pyX.X2.7이나 3.2와 같은 파이썬의 주와 부 버전입니다.

distutils.dist.DistributionMetadata 클래스와 read_pkg_file() 메서드를 사용하여, 이 정적 파일을 다시 읽을 수 있습니다:

>>> from distutils.dist import DistributionMetadata
>>> metadata = DistributionMetadata()
>>> metadata.read_pkg_file(open('distribute-0.6.8-py2.7.egg-info'))
>>> metadata.name
'distribute'
>>> metadata.version
'0.6.8'
>>> metadata.description
'Easily download, build, install, upgrade, and uninstall Python packages'

클래스를 메타 데이터 파일 경로로 인스턴스 화하여 해당 값을 로드 할 수도 있음에 유의하십시오:

>>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info'
>>> DistributionMetadata(pkg_info_path).name
'distribute'