# 6. Distutils 예제

참고

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

이 장에서는 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`는 리스트이므로, 여러 모듈을 지정할 수 있습니다, 예를 들어 `foo`와 `bar` 모듈을 배포한다면, 설정은 다음과 같습니다:

    <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=[''],
          )

그러나 더 일반적으로는, 같은 패키지(또는 서브 패키지)에 있는 여러 모듈을 배포하고자 합니다. 예를 들어, `foo`와 `bar` 모듈이 패키지 `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) must 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)

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

    $ 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.X`는 `2.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'