Python

Python 2.5의 새로운 기능

저자:

A.M. Kuchling

이 문서는 Python 2.5의 새로운 기능들을 설명합니다. Python 2.5의 최종 버전은 2006년 8월로 예정되어 있으며, PEP 356 에서 계획된 출시 일정을 확인할 수 있습니다. Python 2.5는 2006년 9월 19일에 출시되었습니다.

Python 2.5의 변화는 언어와 라이브러리 개선이 조화롭게 섞인 결과입니다. 특히 여러 유용한 패키지들이 추가됨에 따라 라이브러리 강화가 Python 사용자 커뮤니티에 더욱 중요하게 작용할 것입니다. 새로운 모듈로는 XML 처리를 위한 ElementTree(xml.etree), SQLite 데이터베이스 모듈(sqlite), 그리고 C 함수 호출을 위한 ctypes 모듈이 포함됩니다.

언어적 변화는 중간 정도의 중요성을 가집니다. 몇 가지 유용한 새로운 기능들이 추가되었으나, 대부분 매일 사용하는 핵심 기능은 아닙니다. 드디어 독특한 구문을 사용하여 조건부 표현식이 추가되었습니다(섹션 PEP 308: 조건부 표현식 참조). 새롭게 도입된 ‘with’ 문은 정리 코드를 더 쉽게 작성할 수 있게 해줍니다(섹션 PEP 343: ‘with’ 문 참조). 이제 제너레이터에 값을 전달할 수 있으며(섹션 PEP 342: 새로운 제너레이터 기능 참조), 임포트가 절대 경로 또는 상대 경로로 표시됩니다(섹션 PEP 328: 절대 및 상대 임포트 참조). 또한 예외 처리의 몇몇 특수한 경우들이 더 잘 처리되도록 개선되었습니다(섹션 PEP 341: 통합된 try/except/finally 참조). 이러한 모든 개선 사항은 가치가 있지만, 각각 특정 언어 기능에 대한 개선일 뿐 Python의 전체적인 의미론을 널리 수정하는 것은 아닙니다.

언어 및 라이브러리 추가 외에도 소스 트리 전반에 걸쳐 다양한 개선과 버그 수정이 이루어졌습니다. SVN 변경 로그를 확인한 결과, Python 2.4와 2.5 사이에서 353개의 패치가 적용되었고 458개의 버그가 수정되었습니다.(두 수치 모두 실제보다 적게 측정되었을 가능성이 큽니다.)

이 문서는 새로운 기능에 대한 완전한 명세를 제공하기보다는 유용한 예제를 사용하여 변경 사항을 간략하게 소개합니다. 자세한 내용은 항상 https://docs.python.org의 Python 2.5 문서를 참조하십시오. 전체 구현 및 설계 근거를 이해하려면 특정 새 기능에 대한 PEP를 참조하십시오.

이 문서에 대한 의견이나 제안, 오류 보고를 환영합니다. 작성자에게 이메일을 보내거나 Python 버그 추적기에 버그를 등록해 주십시오.

PEP 308: 조건부 표현식

오랫동안 많은 사용자들이 조건부 표현식을 작성하는 방법을 요청해 왔습니다. 조건부 표현식이란 불리언(Boolean) 값이 참인지 거짓인지에 따라 값 A 또는 값 B를 반환하는 표현식입니다. 조건부 표현식을 사용하면 다음과 동일한 효과를 내는 단일 할당 문을 작성할 수 있습니다:

if condition:
    x = true_value
else:
    x = false_value

python-dev와 comp.lang.python 모두에서 구문에 대한 지루한 논의가 끊임없이 이어졌습니다. 투표 결과 과반수의 투표자가 어떤 형태로든 조건 표현식을 원한다는 사실이 밝혀졌으나, 압도적인 다수가 선호하는 특정 문법은 없었습니다. 후보에는 C 언어의 cond ? true_v : false_v, if cond then true_v else false_v 및 기타 16가지 변형이 포함되었습니다.

Guido van Rossum은 결국 다음과 같은 의외의 문법을 선택했습니다:

x = true_value if condition else false_value

기존의 불리언(Boolean) 표현식과 마찬가지로 평가가 게으르게(lazy) 이루어지므로, 평가 순서가 다소 바뀝니다. 중간에 있는 condition 표현식이 먼저 평가되며, true_value 표현식은 조건이 참일 때만 평가됩니다. 마찬가지로 false_value 표현식은 조건이 거짓일 때만 평가됩니다.

이 문법은 다소 낯설고 역방향처럼 보일 수 있습니다. 왜 조건문이 C 언어의 c ? x : y 와 같이 앞에 오지 않고 표현식의 중간 에 위치할까요? 이 결정은 표준 라이브러리의 모듈들에 새 문법을 적용해 보고 결과 코드가 어떻게 읽히는지 확인하여 검토되었습니다. 조건 표현식이 사용되는 많은 경우에서 한 값은 ‘일반적인 경우’이고 다른 하나는 조건이 충족되지 않는 드문 상황에서만 사용되는 ‘예외적인 경우’인 경우가 많습니다. 조건 문법을 사용하면 이러한 패턴이 훨씬 더 명확하게 드러납니다:

contents = ((doc + '\n') if doc else '')

저는 위의 문장을 다음과 같이 해석했습니다. “여기서 contents 는 보통 doc+'\n' 의 값을 할당받으며, 때때로 doc 이 비어 있는 특별한 경우에는 빈 문자열을 반환합니다.” 명확하게 일반적인 경우와 예외적인 경우가 나뉘지 않는 상황에서 조건 표현식을 자주 사용할 일은 없을 것 같습니다.

조건 표현식을 괄호로 감싸야 하는지에 대한 논의가 있었습니다. 파이썬 언어 문법상 괄호를 필수적으로 요구하지 않기로 결정했지만, 스타일 측면에서는 항상 사용하는 것을 권장합니다. 다음 두 문장을 비교해 보십시오:

# 첫 번째 버전 -- 괄호 없음
level = 1 if logging else 0

# 두 번째 버전 -- 괄호 포함
level = (1 if logging else 0)

첫 번째 버전의 경우, 독자의 시선이 문장을 ‘level = 1’, ‘if logging’, ‘else 0’으로 나누어 파악하여 조건에 따라 level 에 할당이 수행되는지 여부가 결정된다고 오해할 수 있습니다. 두 번째 버전은 할당이 항상 실행되며 단지 두 값 중 하나를 선택하는 것임을 명확하게 보여주므로 제가 보기에는 더 읽기 좋습니다.

괄호를 포함하는 또 다른 이유는 리스트 컴프리헨션과 람다(lambda)의 몇몇 특이한 조합이 잘못된 조건 표현식처럼 보일 수 있기 때문입니다. 관련 사례는 PEP 308 을 참조하십시오. 조건 표현식을 괄호로 감싸면 이러한 문제를 피할 수 있습니다.

더 보기

PEP 308 - 조건 표현식

Guido van Rossum과 Raymond D. Hettinger가 작성한 PEP이며, Thomas Wouters가 구현했습니다.

PEP 309: 부분적 함수 적용

functools 모듈은 함수형 프로그래밍 스타일을 위한 도구들을 포함합니다.

이 모듈의 유용한 도구 중 하나는 partial() 함수입니다. 함수형 스타일로 작성된 프로그램에서는 일부 매개변수가 이미 채워진 기존 함수의 변형을 생성하고 싶을 때가 있습니다. 파이썬 함수 f(a, b, c) 를 고려해 보십시오. f(1, b, c) 와 동일한 동작을 하는 새 함수 g(b, c) 를 만들 수 있는데, 이를 “부분적 함수 적용”이라고 합니다.

partial()(function, arg1, arg2, ... kwarg1=value1, kwarg2=value2) 인자를 받습니다. 생성된 객체는 호출 가능(callable)하므로, 이를 호출하여 채워진 인자와 함께 function 을 실행할 수 있습니다.

작지만 실제적인 예시입니다:

import functools

def log (message, subsystem):
    "Write the contents of 'message' to the specified subsystem."
    print '%s: %s' % (subsystem, message)
    ...

server_log = functools.partial(log, subsystem='server')
server_log('Unable to open socket')

PyGTK를 사용하는 프로그램의 또 다른 예시입니다. 여기서는 문맥에 맞는 팝업 메뉴가 동적으로 생성됩니다. 메뉴 옵션에 제공되는 콜백은 첫 번째 인자가 채워진 open_item() 메서드의 부분적 적용 버전입니다.

...
class Application:
    def open_item(self, path):
       ...
    def init (self):
        open_func = functools.partial(self.open_item, item_path)
        popup_menu.append( ("Open", open_func, 1) )

functools 모듈의 또 다른 함수는 적절하게 동작하는 데코레이터를 작성하는 데 도움이 되는 update_wrapper(wrapper, wrapped) 함수입니다. update_wrapper() 는 wrapper 함수의 이름, 모듈 및 docstring 속성을 복사하여 래핑된 함수 내부에서 발생하는 트레이스백을 이해하기 쉽게 만듭니다. 예를 들어 다음과 같이 쓸 수 있습니다:

def my_decorator(f):
    def wrapper(*args, **kwds):
        print 'Calling decorated function'
        return f(*args, **kwds)
    functools.update_wrapper(wrapper, f)
    return wrapper

wraps() 는 자체 데코레이터 내에서 래핑된 함수의 정보를 복사하기 위해 사용할 수 있는 데코레이터입니다. 이전 예제의 다른 버전은 다음과 같습니다:

def my_decorator(f):
    @functools.wraps(f)
    def wrapper(*args, **kwds):
        print 'Calling decorated function'
        return f(*args, **kwds)
    return wrapper

더 보기

PEP 309 - 부분적 함수 적용

Peter Harris가 제안하고 작성한 PEP이며, Hye-Shik Chang과 Nick Coghlan이 구현하였고 Raymond Hettinger가 조정하였습니다.

PEP 314: 파이썬 소프트웨어 패키지용 메타데이터 v1.1

Distutils에 간단한 종속성 지원이 추가되었습니다. 이제 setup() 함수는 requires, provides, obsoletes 키워드 인자를 갖습니다. sdist 명령을 사용하여 소스 배포판을 빌드할 때 관련 종속성 정보가 PKG-INFO 파일에 기록됩니다.

새로운 키워드 인자로 download_url 이 추가되었으며, 이는 패키지의 소스 코드가 포함된 URL로 설정해야 합니다. 이를 통해 이제 패키지 색인에서 항목을 검색하고, 특정 패키지의 종속성을 파악하며, 필요한 패키지들을 다운로드할 수 있습니다.

VERSION = '1.0'
setup(name='PyPackage',
      version=VERSION,
      requires=['numarray', 'zlib (>=1.1.4)'],
      obsoletes=['OldPackage']
      download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
                    % VERSION),
     )

https://pypi.org의 파이썬 패키지 색인에 추가된 또 다른 기능은 패키지의 소스 및 바이너리 아카이브를 저장하는 것입니다. 새로운 upload Distutils 명령을 통해 레포지토리에 패키지를 업로드할 수 있습니다.

패키지를 업로드하기 전에, 먼저 sdist Distutils 명령을 사용하여 배포판을 빌드할 수 있어야 합니다. 빌드가 성공하면 python setup.py upload 를 실행하여 패키지를 PyPI 아카이브에 추가할 수 있습니다. 선택적으로 --sign--identity 옵션을 제공하여 패키지에 GPG 서명을 할 수도 있습니다.

패키지 업로드 기능은 Martin von Löwis와 Richard Jones가 구현했습니다.

더 보기

PEP 314 - 파이썬 소프트웨어 패키지용 메타데이터 v1.1

A.M. Kuchling, Richard Jones, 그리고 Fred Drake가 제안하고 작성한 PEP이며, Richard Jones와 Fred Drake가 구현했습니다.

PEP 328: 절대 및 상대 임포트

PEP 328 의 단순한 부분은 파이썬 2.4에서 구현되었습니다. 이제 from ... import ... 문을 사용하여 모듈에서 가져오는 이름을 괄호로 묶어 여러 다양한 이름을 더 쉽게 임포트할 수 있게 되었습니다.

더 복잡한 부분은 파이썬 2.5에서 구현되었습니다. 모듈을 임포트할 때 절대 또는 패키지 상대 임포트를 사용하도록 지정할 수 있습니다. 향후 파이썬 버전에서는 절대 임포트가 기본값이 되도록 나아갈 계획입니다.

다음과 같은 구조의 패키지 디렉토리가 있다고 가정해 봅시다:

pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py

이것은 pkg.mainpkg.string 하위 모듈을 포함하는 pkg 라는 패키지를 정의합니다.

main.py 모듈의 코드를 살펴보십시오. 여기서 import string 문을 실행하면 어떤 일이 벌어질까요? 파이썬 2.4 및 그 이전 버전에서는 먼저 패키지 디렉토리에서 상대 임포트를 수행하여 pkg/string.py 를 찾고, 해당 파일의 내용을 pkg.string 모듈로 임포트하며, 이 모듈이 pkg.main 모듈의 네임스페이스에서 string 이라는 이름으로 바인딩됩니다.

pkg.string 이 원했던 것이라면 괜찮습니다. 하지만 파이썬 표준 string 모듈을 원한다면 어떨까요? pkg.string 을 무시하고 표준 모듈을 찾는 깔끔한 방법이 없습니다. 일반적으로는 약간 깔끔하지 못한 방식인 sys.modules 의 내용을 확인해야 했습니다. Holger Krekel의 py.std 패키지는 표준 라이브러리에서 임포트하는 더 깔끔한 방법인 import py; py.std.string.join() 을 제공하지만, 해당 패키지가 모든 파이썬 설치 환경에서 제공되는 것은 아닙니다.

상대 임포트에 의존하는 코드는 읽을 때 덜 명확합니다. 독자가 어떤 모듈, 즉 string 인지 아니면 pkg.string 인지 구분하기 어려울 수 있기 때문입니다. 파이썬 사용자들은 머지않아 자신의 패키지 하위 모듈 이름에 표준 라이브러리 모듈 이름을 중복해서 사용하지 않는다는 것을 알게 되었지만, 향후 파이썬 버전에서 추가된 새 모듈이 당신의 하위 모듈 이름과 겹치는 것까지는 막을 수 없습니다.

파이썬 2.5부터는 from __future__ import absolute_import 지시어를 사용하여 import 의 동작 방식을 절대 임포트로 전환할 수 있습니다. 이 절대 임포트 방식은 향후 버전(아마도 파이썬 2.7)에서 기본값이 될 것입니다. 한 번 절대 임포트가 기본이 되면 import string 은 항상 표준 라이브러리 버전을 찾게 됩니다. 사용자는 가능한 한 많은 곳에서 절대 임포트를 사용하기 시작하는 것이 권장되므로, 코드에 from pkg import string 을 쓰는 방식부터 연습해 보시는 것이 좋습니다.

from ... import 형태를 사용할 때 모듈 이름 앞에 점(.)을 추가함으로써 여전히 상대 임포트를 수행할 수 있습니다:

# pkg.string에서 이름 임포트
from .string import name1, name2
# pkg.string 임포트
from . import string

이것은 현재 패키지를 기준으로 한 string 모듈을 임포트하며, 따라서 pkg.main 에서 이 코드는 pkg.string 으로부터 name1name2 를 가져옵니다. 앞에 더 많은 점을 추가하면 현재 패키지의 상위 패키지부터 시작하는 상대 임포트를 수행합니다. 예를 들어, A.B.C 모듈의 코드는 다음과 같이 수행할 수 있습니다:

from . import D                 # A.B.D 임포트
from .. import E                # A.E 임포트
from ..F import G               # A.F.G 임포트

앞에 붙는 점은 import modname 형태의 임포트 문에서는 사용할 수 없으며, 오직 from ... import 형태에서만 사용할 수 있습니다.

더 보기

PEP 328 - 임포트: 다중 행 및 절대/상대

Aahz가 작성한 PEP이며, Thomas Wouters가 구현했습니다.

https://pylib.readthedocs.io/

py.std 패키지를 포함하는 Holger Krekel의 py 라이브러리입니다.

PEP 338: 모듈을 스크립트로 실행하기

파이썬 2.4에서 모듈을 스크립트로 실행하기 위해 추가된 -m 스위치가 몇 가지 기능을 더 갖추게 되었습니다. 이제 이 스위치는 파이썬 인터프리터 내부의 C 코드로 구현되는 대신, 새로운 모듈인 runpy 의 구현을 사용합니다.

runpy 모듈은 더욱 정교한 임포트 메커니즘을 구현하여 이제 pychecker.checker 와 같은 패키지 내의 모듈을 실행할 수 있습니다. 또한 이 모듈은 zipimport 모듈과 같은 대안적인 임포트 메커니즘을 지원합니다. 이는 .zip 아카이브의 경로를 sys.path 에 추가한 다음, -m 스위치를 사용하여 해당 아카이브에서 코드를 실행할 수 있음을 의미합니다.

더 보기

PEP 338 - 모듈을 스크립트로 실행하기

Nick Coghlan이 작성하고 구현한 PEP.

PEP 341: 통합된 try/except/finally

파이썬 2.5 이전까지 try 문은 두 가지 형태가 있었습니다. 코드가 항상 실행되도록 보장하는 finally 블록을 사용하거나, 특정 예외를 잡기 위한 하나 이상의 except 블럭을 사용할 수 있었습니다. 통합된 버전의 올바른 바이트코드를 생성하는 것이 복잡하고 통합된 문구의 의미가 명확하지 않았기 때문에, except 블록과 finally 블록을 동시에 결합할 수는 없었습니다.

Guido van Rossum은 except 블록과 finally 블록을 결합하는 것과 동등한 기능을 지원하는 Java를 연구하며 해당 문장이 어떤 의미여야 하는지 명확히 파악했습니다. 파이썬 2.5에서 이제 다음과 같이 작성할 수 있습니다:

try:
    block-1 ...
except Exception1:
    handler-1 ...
except Exception2:
    handler-2 ...
else:
    else-block
finally:
    final-block

block-1 의 코드가 실행됩니다. 코드가 예외를 발생시키면 다양한 except 블록을 검사합니다: 예외가 Exception1 클래스인 경우 handler-1 이 실행되고, 그렇지 않고 Exception2 클래스인 경우 handler-2 가 실행되는 식입니다. 예외가 발생하지 않으면 else-block 이 실행됩니다.

이전 상황과 관계없이 코드 블록이 완료되고 발생한 예외가 처리되면 final-block 이 실행됩니다. 예외 처리기나 else-block 에서 오류가 발생하여 새로운 예외가 발생하더라도 final-block 의 코드는 여전히 실행됩니다.

더 보기

PEP 341 - try-except 및 try-finally 통합

Georg Brandl이 작성하고 Thomas Lee가 구현한 PEP.

PEP 342: 새로운 제너레이터 기능

파이썬 2.5는 제너레이터에 값을 전달 하는 간단한 방법을 추가합니다. 파이썬 2.3에서 도입된 것처럼 제너레이터는 출력만 생성하며, 이터레이터를 만들기 위해 제너레이터 코드가 호출된 후에는 실행이 재개될 때 함수에 새로운 정보를 전달할 방법이 없었습니다. 때로는 정보를 전달하는 기능이 유용할 수 있습니다. 이에 대한 편법적인 해결책으로는 제너레이터 코드가 전역 변수를 참조하게 하고 그 값을 변경하거나, 호출자가 수정할 수 있는 가변 객체를 전달하는 방식 등이 있었습니다.

기본적인 제너레이터에 대한 기억을 되살리기 위해 간단한 예제를 소개합니다:

def counter (maximum):
    i = 0
    while i < maximum:
        yield i
        i += 1

counter(10) 를 호출하면 0부터 9까지의 값을 반환하는 이터레이터가 생성됩니다. yield 문을 만나면 이터레이터는 제공된 값을 반환하고 로컬 변수를 유지한 채 함수의 실행을 일시 중단합니다. 이후 이터레이터의 next() 메서드를 호출하면 yield 문 다음부터 실행이 재개됩니다.

파이썬 2.3에서 yield`은 문(statement)이었으며 어떠한 값도 반환하지 않았습니다. 파이썬 2.5에서 :keyword:!yield`는 이제 표현식(expression)이며, 변수에 할당하거나 다른 연산을 수행할 수 있는 값을 반환합니다:

val = (yield i)

위 예제와 같이 반환된 값으로 무언가를 수행할 때는 항상 yield 표현식을 괄호로 묶는 것을 권장합니다. 괄호가 항상 필요한 것은 아니지만, 필요할 때마다 기억하는 것보다 항상 사용하는 것이 더 편리하기 때문입니다.

(PEP 342 은 정확한 규칙을 설명합니다. 즉, 대입문의 우측에 있는 최상위 표현식에서 발생하는 경우를 제외하고는 yield 표현식을 항상 괄호로 묶어야 한다는 것입니다. 이는 val = yield i 와 같이 쓸 수 있지만, val = (yield i) + 12 처럼 연산이 포함된 경우에는 괄호를 사용해야 함을 의미합니다.)

제너레이터의 send(value) 메서드를 호출하여 제너레이터에 값을 전달합니다. 그 후 제너레이터 코드가 재개되며 yield 표현식이 지정된 을 반환합니다. 일반적인 next() 메서드가 호출되면 yieldNone 을 반환합니다.

내부 카운터의 값을 변경할 수 있도록 수정된 이전 예제입니다.

def counter (maximum):
    i = 0
    while i < maximum:
        val = (yield i)
        # 값이 제공되면, 카운터를 변경합니다
        if val is not None:
            i = val
        else:
            i += 1

다음은 카운터를 변경하는 예시입니다:

>>> it = counter(10)
>>> print it.next()
0
>>> print it.next()
1
>>> print it.send(8)
8
>>> print it.next()
9
>>> print it.next()
Traceback (most recent call last):
  File "t.py", line 15, in ?
    print it.next()
StopIteration

yield 은 대개 None 을 반환하므로 항상 이 경우를 확인해야 합니다. 제너레이터 함수를 재개하는 데 send() 메서드만 사용된다는 것이 확실하지 않다면 표현식에서 그 값을 그대로 사용하지 마십시오.

send() 외에도 제너레이터에 두 가지 새로운 메서드가 추가되었습니다.

  • throw(type, value=None, traceback=None) 는 제너레이터 내부에서 예외를 발생시키는 데 사용됩니다. 예외는 제너레이터의 실행이 일시 중지된 yield 표현식에 의해 발생합니다.

  • close() 는 반복을 종료하기 위해 제너레이터 내부에서 새로운 GeneratorExit 예외를 발생시킵니다. 이 예외를 받으면 제너레이터 코드는 반드시 GeneratorExit 또는 StopIteration 을 발생시켜야 합니다. GeneratorExit 예외를 잡아 값을 반환하는 것은 허용되지 않으며 RuntimeError 를 유발합니다. 함수가 다른 예외를 발생시키는 경우, 해당 예외는 호출자에게 전파됩니다. 또한 제너레이터가 가비지 컬렉션될 때 파이썬의 가비지 컬렉터에 의해 close() 도 호출됩니다.

    GeneratorExit 이 발생할 때 정리 코드를 실행해야 하는 경우, GeneratorExit 을 잡는 대신 try: ... finally: 구문을 사용할 것을 권장합니다.

이러한 변경의 누적된 효과는 제너레이터를 단방향 정보 제공자에서 생산자와 소비자 역할을 모두 수행하는 존재로 변화시키는 것입니다.

제너레이터는 또한 서브루틴의 더 일반화된 형태인 코루틴 이 됩니다. 서브루틴은 한 지점에서 진입하고 다른 지점(함수의 시작 부분과 return 문)에서 나가지만, 코루틴은 여러 다른 지점(yield 문)에서 진입, 종료 및 재개가 가능합니다. 우리는 파이썬에서 코루틴을 효과적으로 사용하는 패턴을 정립해야 합니다.

close() 메서드의 추가에는 중요하지만 명백하지 않은 부수 효과가 있습니다. 제너레이터가 가비지 컬렉션될 때 close() 가 호출되므로, 이는 제너레이터가 파괴되기 전에 마지막으로 실행될 기회를 한 번 얻는다는 것을 의미합니다. 이로 인해 제너레이터 내의 try...finally 문이 확실하게 작동하도록 보장되며, 이제 finally 절이 항상 실행될 기회를 갖게 됩니다. 따라서 yield 문과 try...finally 구문을 혼합할 수 없다는 문법적 제한이 제거되었습니다. 이는 사소한 언어적 세부 사항처럼 보일 수 있지만, 제너레이터와 try...finally 를 사용하는 것은 PEP 343 에서 설명하는 with 문을 구현하기 위해 실제로 필요합니다. 다음 섹션에서 이 새로운 문법에 대해 살펴보겠습니다.

이 변경으로 인한 또 다른 생소한 효과는 다음과 같습니다. 이전에는 제너레이터의 gi_frame 속성이 항상 프레임 객체였으나, 이제 제너레이터가 소진된 후에는 gi_frameNone 이 될 수 있습니다.

더 보기

PEP 342 - 강화된 제너레이터를 통한 코루틴

Guido van Rossum과 Phillip J. Eby가 작성하고 Phillip J. Eby가 구현한 PEP입니다. 코루틴으로서 제너레이터를 활용하는 몇 가지 고급 사례들이 포함되어 있습니다.

이 기능의 초기 버전은 Raymond Hettinger에 의한 PEP 288 과 Samuele Pedroni에 의한 PEP 325 에서 제안되었습니다.

https://en.wikipedia.org/wiki/Coroutine

코루틴에 대한 위키백과 항목.

https://web.archive.org/web/20160321211320/http://www.sidhe.org/~dan/blog/archives/000178.html

Dan Sugalski가 작성한 Perl 관점에서의 코루틴 설명.

PEP 343: ‘with’ 문

with 문은 기존에 정리 코드가 실행되는지 확인하기 위해 try...finally 블록을 사용하던 코드를 명확하게 해줍니다. 이 섹션에서는 이 문장이 일반적으로 어떻게 사용되는지 논의하고, 다음 섹션에서 구현 세부 사항과 이 문법을 지원하는 객체를 작성하는 방법을 설명하겠습니다.

with 문은 다음과 같은 기본 구조를 가진 새로운 제어 흐름 구조입니다:

with expression [as variable]:
    with-block

표현식이 평가되며, 그 결과는 컨텍스트 관리 프로토콜을 지원하는 객체여야 합니다(즉, __enter__()__exit__() 메서드를 보유해야 함).

객체의 __enter__()with-block 이 실행되기 전에 호출되어 설정 코드를 실행할 수 있습니다. 또한 제공된 경우 결과값이 변수 라는 이름으로 바인딩될 수 있습니다. (주의: 변수표현식 의 결과가 할당되는 것은 아닙니다.)

with-block 실행이 끝나면 블록에서 예외가 발생했더라도 객체의 __exit__() 메서드가 호출되어 정리 코드를 수행할 수 있습니다.

파이썬 2.5에서 이 문을 활성화하려면 모듈에 다음 지시어를 추가해야 합니다:

from __future__ import with_statement

이 문은 파이썬 2.6에서 항상 활성화됩니다.

일부 표준 파이썬 객체가 이제 컨텍스트 관리 프로토콜을 지원하며 ‘with’ 문과 함께 사용할 수 있습니다. 파일 객체가 그 예시 중 하나입니다:

with open('/etc/passwd', 'r') as f:
    for line in f:
        print line
        ... more processing code ...

이 문장이 실행된 후, 블록 중간에 for 루프가 예외를 발생시켰더라도 f 의 파일 객체는 자동으로 닫힙니다.

참고

이 경우, __enter__()self 를 반환하기 때문에 fopen() 에 의해 생성된 것과 동일한 객체입니다.

threading 모듈의 락(lock)과 조건 변수도 ‘with’ 문을 지원합니다:

lock = threading.Lock()
with lock:
    # 코드의 임계 영역
    ...

블록이 실행되기 전에 락을 획득하고, 블록이 완료되면 항상 해제합니다.

decimal 모듈의 새로운 localcontext() 함수를 사용하면 계산에 필요한 정밀도와 반올림 특성을 포함하는 현재 십진수 컨텍스트를 쉽게 저장하고 복원할 수 있습니다:

from decimal import Decimal, Context, localcontext

# 기본 정밀도 28자리로 표시
v = Decimal('578')
print v.sqrt()

with localcontext(Context(prec=16)):
    # 이 블록의 모든 코드는 16자리의 정밀도를 사용합니다.
    # 블록을 나가면 원래 컨텍스트로 복구됩니다.
    print v.sqrt()

컨텍스트 관리자 작성하기

내부적으로 ‘with’ 문은 상당히 복잡합니다. 대부분의 사용자는 기존 객체와 함께 ‘with’를 사용할 뿐 이러한 세부 사항을 알 필요가 없으므로, 원하는 경우 이 섹션의 나머지 부분은 건너뛰어도 좋습니다. 새로운 객체를 만드는 작성자는 기본 구현의 상세 내용을 이해해야 하므로 계속 읽어 나가야 합니다.

컨텍스트 관리 프로토콜에 대한 고수준 설명은 다음과 같습니다:

  • 표현식이 평가되어 “컨텍스트 관리자”라고 불리는 객체가 생성되어야 합니다. 컨텍스트 관리자는 반드시 __enter__()__exit__() 메서드를 가져야 합니다.

  • 컨텍스트 관리자의 __enter__() 메서드가 호출됩니다. 반환된 값은 VAR 에 할당됩니다. 'as VAR' 절이 없는 경우 해당 값은 단순히 버려집니다.

  • BLOCK 내의 코드가 실행됩니다.

  • BLOCK 에서 예외가 발생하면, sys.exc_info() 에서 반환하는 값과 동일한 예외 세부 정보와 함께 __exit__(type, value, traceback) 이 호출됩니다. 메서드의 반환값은 예외를 다시 발생시킬지 여부를 결정합니다. False 계열의 값이면 예외가 재발생하고, True 이면 예럼이 억제됩니다. 예외를 억제하는 경우는 드문데, 그렇게 하면 ‘with ‘ 문을 포함한 코드를 작성한 사람이 문제가 발생했다는 사실을 알 수 없기 때문입니다.

  • BLOCK 에서 예외가 발생하지 않더라도 __exit__() 메서드는 여전히 호출되지만, type, value, traceback 은 모두 None 입니다.

예제를 통해 생각해 보겠습니다. 상세한 코드를 제시하지는 않겠지만 트랜잭션을 지원하는 데이터베이스에 필요한 메서드들을 간략하게 스케치하겠습니다.

(데이터베이스 용어가 익숙하지 않은 분들을 위한 설명: 데이터베이스에 대한 일련의 변경 사항은 트랜잭션으로 그룹화됩니다. 트랜잭션은 모든 변경 사항이 데이터베이스에 기록되는 커밋(committed)되거나, 모든 변경 사항이 폐기되어 데이터베이스가 변하지 않는 롤백(rolled back)될 수 있습니다. 자세한 내용은 데이터베이스 교과서를 참조하십시오.)

데이터베이스 연결을 나타내는 객체가 있다고 가정해 보겠습니다. 우리의 목표는 사용자가 다음과 같이 코드를 작성할 수 있게 하는 것입니다:

db_connection = DatabaseConnection()
with db_connection as cursor:
    cursor.execute('insert into ...')
    cursor.execute('delete from ...')
    # ... 추가 작업 ...

블록 내의 코드가 문제없이 실행되면 트랜잭션이 커밋되어야 하고, 예외가 발생하면 롤백되어야 합니다. 제가 가정한 DatabaseConnection 의 기본 인터페이스는 다음과 같습니다:

class DatabaseConnection:
    # 데이터베이스 인터페이스
    def cursor (self):
        "커서 객체를 반환하고 새 트랜잭션을 시작함"
    def commit (self):
        "현재 트랜잭션을 커밋함"
    def rollback (self):
        "현재 트랜잭션을 롤백함"

__enter__() 메서드는 새 트랜잭션을 시작하기만 하면 되므로 꽤 간단합니다. 이 애플리케이션의 경우 결과로 생성된 커서 객체가 유용하므로, 해당 메서드는 이를 반환합니다. 그러면 사용자는 ‘with ‘ 문에 as cursor 를 추가하여 커서를 변수 이름에 바인딩할 수 있습니다.

class DatabaseConnection:
    ...
    def __enter__ (self):
        # 새 트랜잭션을 시작하는 코드
        cursor = self.cursor()
        return cursor

__exit__() 메서드는 대부분의 작업이 수행되어야 하는 곳이므로 가장 복잡합니다. 이 메서드는 예외 발생 여부를 확인해야 합니다. 예외가 없으면 트랜잭션이 커밋되고, 예외가 있으면 트랜잭션이 롤백됩니다.

아래 코드에서 실행은 함수의 끝까지 진행되고 기본값인 None 을 반환합니다. None 은 False이므로 예외가 자동으로 재발생합니다. 원한다면 표시된 위치에 return 문을 추가하여 더 명시적으로 작성할 수도 있습니다.

class DatabaseConnection:
    ...
    def __exit__ (self, type, value, tb):
        if tb is None:
            # 예외 없음, 커밋
            self.commit()
        else:
            # 예외 발생, 롤백
            self.rollback()
            # return False

contextlib 모듈

새로운 contextlib 모듈은 ‘with’ 문과 함께 사용할 객체를 작성하는 데 유용한 몇 가지 함수와 데코레이터를 제공합니다.

이 데코레이터의 이름은 @~contextlib.contextmanager 이며, 새 클래스를 정의하는 대신 단일 제너레이터 함수를 작성할 수 있게 해줍니다. 제너레이터는 반드시 하나의 값만 yield해야 합니다. yield 까지의 코드는 __enter__() 메서드로 실행되고, yield된 값은 방법의 반환값이 되어 ‘with ‘ 문의 as 절에 있는 변수에 바인딩됩니다(있는 경우). yield 이후의 코드는 __exit__() 메서드에서 실행됩니다. 블록 내에서 발생한 모든 예외는 yield 문에 의해 던져집니다.

이전 섹션의 데이터베이스 예제는 이 데코레이터를 사용하여 다음과 같이 작성할 수 있습니다:

from contextlib import contextmanager

@contextmanager
def db_transaction (connection):
    cursor = connection.cursor()
    try:
        yield cursor
    except:
        connection.rollback()
        raise
    else:
        connection.commit()

db = DatabaseConnection()
with db_transaction(db) as cursor:
    ...

contextlib 모듈에는 여러 개의 컨텍스트 관리자를 결합하는 nested(mgr1, mgr2, ...) 함수가 있어 중첩된 ‘with’ 문을 작성할 필요가 없습니다. 이 예제에서는 단일 ‘with’ 문이 데이터베이스 트랜잭션을 시작함과 동시에 스레드 락을 획득합니다:

lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):
    ...

마지막으로, closing(object) 함수는 object 를 반환하여 변수에 바인딩할 수 있게 하며, 블록 끝에서 object.close 를 호출합니다.

import urllib, sys
from contextlib import closing

with closing(urllib.urlopen('http://www.yahoo.com')) as f:
    for line in f:
        sys.stdout.write(line)

더 보기

PEP 343 - “with” 문

Guido van Rossum과 Nick Coghlan이 작성하고 Mike Bland, Guido van Rossum, Neal Norwitz가 구현한 PEP입니다. 이 PEP는 ‘with’ 문을 위해 생성된 코드를 보여주며, 해당 문장이 어떻게 작동하는지 배우는 데 도움이 될 수 있습니다.

contextlib 모듈에 대한 설명서입니다.

PEP 352: 새 스타일 클래스로의 예외

이제 예외 클래스는 고전적인 스타일뿐만 아니라 새로운 스타일의 클래스도 될 수 있으며, 내장된 Exception 클래스와 모든 표준 내장 예외(NameError, ValueError 등)는 이제 모두 새로운 스타일의 클래스입니다.

예외의 상속 계층 구조가 약간 재조정되었습니다. 2.5 버전에서 상속 관계는 다음과 같습니다:

BaseException       # 파이썬 2.5에서 새로 추가됨
|- KeyboardInterrupt
|- SystemExit
|- Exception
   |- (기타 모든 현재 내장 예외)

This rearrangement was done because people often want to catch all exceptions that indicate program errors. KeyboardInterrupt and SystemExit aren’t errors, though, and usually represent an explicit action such as the user hitting Control-C or code calling sys.exit(). A bare except: will catch all exceptions, so you commonly need to list KeyboardInterrupt and SystemExit in order to re-raise them. The usual pattern is:

try:
    ...
except (KeyboardInterrupt, SystemExit):
    raise
except:
    # 에러 기록...
    # 프로그램 계속 실행...

In Python 2.5, you can now write except Exception to achieve the same result, catching all the exceptions that usually indicate errors but leaving KeyboardInterrupt and SystemExit alone. As in previous versions, a bare except: still catches all exceptions.

The goal for Python 3.0 is to require any class raised as an exception to derive from BaseException or some descendant of BaseException, and future releases in the Python 2.x series may begin to enforce this constraint. Therefore, I suggest you begin making all your exception classes derive from Exception now. It’s been suggested that the bare except: form should be removed in Python 3.0, but Guido van Rossum hasn’t decided whether to do this or not.

문장 raise "Error occurred" 와 같이 문자열을 예외로 발생시키는 기능은 파이썬 2.5에서 지원 중단(deprecated)되었으며 경고를 발생시킵니다. 목표는 몇 번의 출시를 거쳐 문자열-예외 기능을 제거하는 것입니다.

더 보기

PEP 352 - 예외를 위한 필수 상위 클래스

Brett Cannon과 Guido van Rossum이 작성하고 Brett Cannon이 구현한 PEP입니다.

PEP 353: 인덱스 유형으로 ssize_t 사용

C API에 대한 광범위한 변경 사항으로, int 대신 새로운 Py_ssize_t 타입 정의를 사용함으로써 64비트 플랫폼에서 인터프리터가 더 많은 데이터를 처리할 수 있게 됩니다. 이 변화는 32비트 플랫폼의 파이썬 용량에 영향을 미치지 않습니다.

파이썬 인터프리터의 여러 부분에서 크기나 개수를 저장하기 위해 C의 int 타입을 사용했습니다. 예를 들어 리스트나 튜플의 아이템 수는 int 에 저장되었습니다. 대부분의 64비트 플랫폼용 C 컴파일러는 여전히 int 를 32비트 타입으로 정의하므로, 이는 리스트가 최대 2**31 - 1 = 2147483647개의 아이템만 담을 수 있음을 의미했습니다. (실제로 64비트 C 컴파일러가 사용할 수 있는 몇 가지 다른 프로그래밍 모델이 있으며, 이에 대한 논의는 https://unix.org/version2/whatsnew/lp64_wp.html를 참고하십시오. 하지만 가장 일반적으로 사용되는 모델은 int 를 32비트로 유지합니다.)

32비트 플랫폼에서는 길이 제한에 도달하기 전에 메모리가 부족해지므로, 아이템 한도가 2147483647인 것은 실제적인 의미가 없습니다. 각 리스트 항목은 포인터를 위한 공간(4바이트)과 항목을 나타내는 PyObject 를 위한 공간이 필요합니다. 2147483647*4는 이미 32비트 주소 공간이 수용할 수 있는 바이트 수를 초과합니다.

그러나 64비트 플랫폼에서는 그만큼의 메모리 주소에 접근할 수 있습니다. 해당 크기의 리스트를 위한 포인터는 단 16 GiB의 공간만 필요하므로, 파이썬 프로그래머가 그렇게 큰 리스트를 구성하는 것은 비합리적이지 않습니다. 따라서 파이썬 인터프리터는 int 이외의 다른 타입을 사용하도록 변경해야 했으며, 이는 64비트 플랫폼에서 64비트 타입이 됩니다. 이 변경으로 인해 64비트 머신에서 호환성 문제가 발생할 수 있으므로, 64비트 사용자가 아직 상대적으로 적은 지금 시점에서 전환을 진행하는 것이 가치가 있다고 판단되었습니다. (5년 또는 10년 후에는 우리 모두가 64비트 머신을 사용할 가능성이 높으며, 그때 전환을 시도하면 훨씬 더 고통스러울 것입니다.)

이 변경은 C 확장 모듈 작성자에게 가장 큰 영향을 미칩니다. 파이썬 문자열과 리스트, 튜플 같은 컨테이너 타입은 이제 크기를 저장하는 데 Py_ssize_t 를 사용합니다. PyList_Size() 와 같은 함수도 이제 Py_ssize_t 를 반환합니다. 따라서 확장 모듈의 코드에서 일부 변수를 Py_ssize_t 로 변경해야 할 수도 있습니다.

PyArg_ParseTuple()Py_BuildValue() 함수에 Py_ssize_t 를 위한 새로운 변환 코드 n 이 추가되었습니다. PyArg_ParseTuple()s#t# 는 여전히 기본적으로 int 를 출력하지만, Python.h 를 포함하기 전에 매크로 PY_SSIZE_T_CLEAN 을 정의하면 이들이 Py_ssize_t 를 반환하도록 할 수 있습니다.

PEP 353 에는 확장 모듈 작성자가 64비트 플랫폼 지원에 대해 학습할 수 있는 변환 가이드라인 섹션이 포함되어 있습니다.

더 보기

PEP 353 - 인덱스 타입으로 ssize_t 사용

Martin von Löwis가 작성하고 구현한 PEP.

PEP 357: ‘__index__’ 메서드

NumPy 개발자들은 새로운 특수 메서드인 __index__() 를 추가함으로써만 해결할 수 있는 문제를 겪었습니다. [start:stop:step] 과 같은 슬라이스 표기법을 사용할 때, start, stop, step 인덱스의 값은 모두 정수(integer) 또는 긴 정수(long integer)여야 합니다. NumPy는 8, 16, 32, 64비트의 부호 있는/없는 정수에 대응하는 다양한 특수 정수 타입을 정의하지만, 이러한 타입들이 슬라이스 인덱스로 사용될 수 있음을 알릴 방법이 없었습니다.

슬라이싱이 기존의 __int__() 메서드를 바로 사용할 수 없는 이유는 이 메서드가 정수 변환을 구현하는 데에도 사용되기 때문입니다. 만약 슬라이싱에 __int__() 를 사용한다면 부동 소수점 숫자도 유효한 슬라이스 인덱스가 될 것이며, 이는 분명히 원치 않는 동작입니다.

대신, __index__() 라는 새로운 특수 메서드가 추가되었습니다. 이 메서드는 인수를 받지 않으며 사용할 슬라이스 인덱스를 나타내는 정수를 반환합니다. 예시는 다음과 같습니다:

class C:
    def __index__ (self):
        return self.value

반환 값은 파이썬 정수 또는 긴 정수여야 합니다. 인터프리터는 반환된 타입이 올바른지 확인하며, 이 요구 사항을 충족하지 못할 경우 TypeError 를 발생시킵니다.

C 확장 모듈이 이 프로토콜을 구현할 수 있도록 C 수준의 PyNumberMethods 구조체에 해당하는 nb_index 슬롯이 추가되었습니다. 확장 코드에서 PyNumber_Index(obj) 를 사용하여 __index__() 함수를 호출하고 그 결과를 가져올 수 있습니다.

더 보기

PEP 357 - 모든 객체를 슬라이싱에 사용할 수 있도록 허용

Travis Oliphant가 작성하고 구현한 PEP.

이외의 언어 변경 사항

다음은 Python 2.5에서 핵심 파이썬 언어에 가해진 모든 변경 사항입니다.

  • dict 타입은 딕셔너리에 키가 포함되어 있지 않을 때 서브 클래스가 기본값을 제공할 수 있도록 하는 새로운 훅을 갖습니다. 키를 찾을 수 없을 때, 딕셔너리의 __missing__(key) 메서드가 호출됩니다. 이 훅은 collections 모듈의 새로운 defaultdict 클래스를 구현하는 데 사용됩니다. 다음 예제는 누락된 키에 대해 0을 반환하는 딕셔너리를 정의합니다:

    class zerodict (dict):
        def __missing__ (self, key):
            return 0
    
    d = zerodict({1:1, 2:2})
    print d[1], d[2]   # Prints 1, 2
    print d[3], d[4]   # Prints 0, 0
    
  • 8비트 및 유니코드 문자열 모두에 일반적인 사용 사례를 간소화하는 새로운 partition(sep)rpartition(sep) 메서드가 추가되었습니다.

    find(S) 메서드는 종종 인덱스를 얻기 위해 사용되며, 이 인덱스는 문자열을 슬라이싱하여 구분자 앞과 뒤의 조각을 가져오는 데 사용됩니다. partition(sep) 는 이러한 패턴을 단일 메서드 호출로 압축하며, 구분자 앞의 부분 문자열, 구분자 자체, 구분자 뒤의 부분 문자열을 포함하는 3-튜플을 반환합니다. 구분자를 찾지 못하면 튜플의 첫 번째 요소는 전체 문자열이 되고 나머지 두 요소는 빈 문자열이 됩니다. rpartition(sep) 도 3-튜플을 반환하지만 문자열 끝부터 검색을 시작하며, 여기서 r 은 ‘reverse’를 의미합니다.

    몇 가지 예시:

    >>> ('http://www.python.org').partition('://')
    ('http', '://', 'www.python.org')
    >>> ('file:/usr/share/doc/index.html').partition('://')
    ('file:/usr/share/doc/index.html', '', '')
    >>> (u'Subject: a quick question').partition(':')
    (u'Subject', u':', u' a quick question')
    >>> 'www.python.org'.rpartition('.')
    ('www.python', '.', 'org')
    >>> 'www.python.org'.rpartition(':')
    ('', '', 'www.python.org')
    

    (Raymond Hettinger의 제안에 따라 Fredrik Lundh가 구현했습니다.)

  • 문자열 타입의 startswith()endswith() 메서드가 이제 확인을 위한 문자열 튜플을 수용합니다.

    def is_image_file (filename):
        return filename.endswith(('.gif', '.jpg', '.tiff'))
    

    (Tom Lynn의 제안에 따라 Georg Brandl이 구현했습니다.)

  • min()max() 내장 함수에 sort()key 인자와 유사한 key 키워드 매개변수가 추가되었습니다. 이 매개변수는 단일 인자를 받아 리스트의 모든 값에 대해 호출되는 함수를 제공하며, min()/max() 는 이 함수로부터 가장 작거나 큰 값을 반환하는 요소를 반환합니다. 예를 들어, 리스트에서 가장 긴 문자열을 찾으려면 다음과 같이 할 수 있습니다:

    L = ['medium', 'longest', 'short']
    # 'longest' 출력
    print max(L, key=len)
    # 'short' 출력, 사전순으로 'short'가 가장 큰 값을 가짐
    print max(L)
    

    (Steven Bethard와 Raymond Hettinger가 기여했습니다.)

  • 새로운 내장 함수인 any()all() 은 이터레이터가 참(true) 또는 거짓(false) 값을 포함하는지 여부를 평가합니다. any() 는 이터레이터에서 반환된 값 중 어느 하나라도 참이면 True 를 반환하고, 그렇지 않으면 False 를 반환합니다. all() 은 이터레이터에서 반환된 모든 값이 참일 때만 True 를 반환합니다. (Guido van Rossum이 제안하고 Raymond Hettinger가 구현했습니다.)

  • 클래스의 __hash__() 메서드 결과가 이제 정수 또는 긴 정수 모두 가능합니다. 긴 정수가 반환되면 해당 값의 해시를 취합니다. 이전 버전에서는 해시 값이 일반 정수여야 했으나, 2.5에서 id() 내장 함수가 항상 음이 아닌 숫자를 반환하도록 변경되었고 사용자들은 종종 __hash__() 메서드에서 id(self) 를 사용하곤 했습니다(권장되지는 않지만요).

  • 이제 모듈의 기본 인코딩은 ASCII입니다. 모듈에 8비트 문자가 포함된 문자열 리터럴이 포함되어 있으면서 인코딩 선언이 없는 경우 이제 구문 오류가 발생합니다. Python 2.4에서는 이것이 경고를 발생시켰으나, 이제는 구문 오류로 처리됩니다. 모듈의 인코딩을 선언하는 방법은 PEP 263 을 참조하십시오. 예를 들어 소스 파일 상단에 다음과 같은 줄을 추가할 수 있습니다:

    # -*- coding: latin1 -*-
    
  • 기본 ASCII 인코딩을 사용하여 유니코드와 변환할 수 없는 8비트 문자열을 비교하려고 할 때 새로운 경고인 UnicodeWarning 이 발생합니다. 이 경우 비교 결과는 False입니다:

    >>> chr(128) == unichr(128)   # chr(128)을 유니코드로 변환할 수 없음
    __main__:1: UnicodeWarning: Unicode equal comparison failed
      to convert both arguments to Unicode - interpreting them
      as being unequal
    False
    >>> chr(127) == unichr(127)   # chr(127)은 변환 가능
    True
    

    이전에는 이 상황에서 UnicodeDecodeError 예외가 발생했으나, 2.5에서는 딕셔너리에 접근할 때 당혹스러운 문제를 일으킬 수 있었습니다. 예를 들어, unichr(128) 을 조회할 때 chr(128) 이 키로 사용되고 있었다면 UnicodeDecodeError 예외가 발생했습니다. 2.5의 다른 변경 사항들로 인해 이 예외는 딕셔너리를 구현하는 dictobject.c 코드에 의해 억제되는 대신 발생하게 되었습니다.

    이러한 비교에서 예외를 발생시키는 것이 원칙적으로는 맞지만, 이 변화가 기존 코드를 망가뜨릴 수 있으므로 대신 UnicodeWarning 을 도입했습니다.

    (Marc-André Lemburg가 구현했습니다.)

  • One error that Python programmers sometimes make is forgetting to include an __init__.py module in a package directory. Debugging this mistake can be confusing, and usually requires running Python with the -v switch to log all the paths searched. In Python 2.5, a new ImportWarning warning is triggered when an import would have picked up a directory as a package but no __init__.py was found. This warning is silently ignored by default; provide the -Wd option when running the Python executable to display the warning message. (Implemented by Thomas Wouters.)

  • 클래스 정의에서 베이스 클래스 목록이 비어 있을 수 있습니다. 예로, 다음은 이제 허용됩니다:

    class C():
        pass
    

    (Brett Cannon이 구현했습니다.)

대화형 인터프리터 변경 사항

대화형 인터프리터에서 quitexit 는 오랜 기간 동안 문자열로 취급되어 왔으며, 이로 인해 신규 사용자가 종료를 시도할 때 어느 정도 유용한 메시지를 볼 수 있었습니다:

>>> quit
'Use Ctrl-D (i.e. EOF) to exit.'

Python 2.5에서 quitexit 은 여전히 자신의 문자열 표현을 생성하면서도 호출 가능한 객체입니다. 이제 초보자들이 quit() 또는 exit() 를 시도하면 예상대로 인터프리터가 종료됩니다. (Georg Brandl이 구현했습니다.)

Python 실행 파일은 이제 표준 긴 옵션인 --help--version 을 지원하며, Windows에서는 도움말 메시지를 표시하기 위한 /? 옵션도 수용합니다. (Georg Brandl이 구현했습니다.)

최적화들`

몇몇 최적화는 2006년 5월 21~28일 아이슬란드 레이캬비크에서 열린 NeedForSpeed 스프린트에서 개발되었습니다. 이 스프린트는 CPython 구현의 속도 향상에 집중했으며, EWT LLC의 후원과 CCP Games의 현지 지원을 받았습니다. 이 스프린트에서 추가된 최적화는 다음 목록에 별도로 표시되어 있습니다.

  • Python 2.4에서 도입될 당시 내장된 setfrozenset 타입은 Python의 딕셔너리 타입을 기반으로 구축되었습니다. 2.5에서는 set 구현을 위해 내부 데이터 구조가 맞춤화되었으며, 그 결과 set이 메모리를 3분의 1만 사용하고 속도도 약간 더 빨라졌습니다. (Raymond Hettinger가 구현했습니다.)

  • 부분 문자열 찾기, 문자열 분할, 문자 맵 인코딩 및 디코딩과 같은 일부 유니코드 작업의 속도가 향상되었습니다. (NeedForSpeed 스프린트에서 Fredrik Lundh와 Andrew Dalke가 부분 문자열 검색 및 분할 개선 사항을 추가했습니다. Walter Dörwald와 Martin von Löwis는 문자 맵 기능을 개선했습니다.)

  • 중간 결과 계산이 줄어들어 long(str, base) 함수가 긴 숫자 문자열에서 더 빠르게 작동합니다. 약 800~1000자리의 문자열에서 성능이 가장 뛰어나며, 이 경우 해당 함수는 6배 더 빠릅니다. (Alan McIntyre가 기여하고 NeedForSpeed 스프린트에서 반영되었습니다.)

  • 이제 for line in file 을 통한 파일 순회와 파일 객체의 read()/readline()/readlines() 메서드 호출을 혼용하는 것은 허용되지 않습니다. 반복문은 내부 버퍼를 사용하지만, read*() 메서드들은 해당 버퍼를 사용하지 않기 때문입니다. 대신 이 메서드들은 버퍼 이후의 데이터를 반환하여 데이터 순서가 섞이는 문제를 발생시킵니다. 이제 반복과 이러한 메서드를 혼용하면 read*() 메서드에서 ValueError 가 발생합니다. (Thomas Wouters가 구현했습니다.)

  • struct 모듈이 이제 구조체 포맷 문자열을 내부 표현으로 컴파일하고 이를 캐싱하여 20%의 속도 향상을 제공합니다. (NeedForSpeed 스프린트에서 Bob Ippolito가 기여했습니다.)

  • re 모듈이 시스템의 malloc()free() 대신 Python의 할당자(allocator) 함수를 사용하도록 변경되어 1~2% 속도가 향상되었습니다. (NeedForSpeed 스프린트에서 Jack Diederich가 기여했습니다.)

  • 코드 생성기의 피홀 최적화기(peephole optimizer)가 이제 수식에서 간단한 상수 폴딩을 수행합니다. 만약 a = 2+3 과 같은 코드를 작성하면, 코드 생성기가 산술 연산을 수행하고 a = 5 에 해당하는 코드를 생성합니다. (Raymond Hettinger가 제안하고 구현했습니다.)

  • 코드 객체가 이제 가장 최근에 종료된 프레임(zombie frame)을 내부 필드에 보관하고 다음 호출 시 재사용하게 되면서 함수 호출 속도가 향상되었습니다. (Michael Hudson이 처음 패치하고 Armin Rigo와 Richard Jones가 수정하여 NeedForSpeed 스프린트에서 반영됨.) 프레임 객체의 크기도 약간 줄어들어 캐시 지역성이 개선되고 메모리 사용량이 다소 감소할 수 있습니다. (Neal Norwitz 기여.)

  • Python의 내장 예외가 이제 새로운 스타일의 클래스로 변경되어 인스턴스 생성 속도가 상당히 빨라졌습니다. 이에 따라 Python 2.5의 예외 처리는 2.4보다 약 30% 더 빠릅니다. (NeedForSpeed 스프린트에서 Richard Jones, Georg Brandl, Sean Reifschneider가 기여했습니다.)

  • 이제 임포트 시 시도된 경로를 캐싱하고 해당 경로의 존재 여부를 기록하여, 인터프리터가 시작할 때 더 적은 횟수의 open()stat() 호출을 수행하도록 합니다. (Martin von Löwis와 Georg Brandl이 기여했습니다.)

새로운 기능, 개선 및 삭제된 모듈

Python 2.5에서 표준 라이브러리에 많은 개선과 버그 수정이 이루어졌습니다. 다음은 모듈 이름의 알파벳 순서로 정리한 주요 변경 사항 목록입니다. 더 상세한 전체 목록을 확인하려면 소스 트리의 Misc/NEWS 파일을 참조하거나 SVN 로그를 살펴보시기 바랍니다.

  • audioop 모듈이 이제 a-LAW 인코딩을 지원하며, u-LAW 인코딩 코드가 개선되었습니다. (Lars Immisch 기여.)

  • codecs 모듈이 증분형(incremental) 코덱을 지원하게 되었습니다. 이제 codec.lookup() 함수는 튜플 대신 CodecInfo 인스턴스를 반환합니다. CodecInfo 인스턴스는 하위 호환성을 유지하기 위해 4-튜플처럼 작동하면서도 encode, decode, incrementalencoder, incrementaldecoder, streamwriter, 그리고 streamreader 속성을 가집니다. 증분형 코덱은 입력을 여러 청크로 받아 출력을 생성할 수 있으며, 그 결과는 전체 입력을 비증분형(non-incremental) 코덱에 전달한 것과 동일합니다. 자세한 내용은 codecs 모듈 문서를 참조하십시오. (Walter Dörwald 설계 및 구현.)

  • collections 모듈에 표준 dict 타입을 상속받는 새로운 타입인 defaultdict 가 추가되었습니다. 이 새로운 타입은 대부분 딕셔너리처럼 작동하지만, 키가 없을 때 기본값을 생성하여 요청한 키 값에 대해 자동으로 딕셔너리에 추가합니다.

    defaultdict 생성자의 첫 번째 인자는 키를 요청했을 때 찾을 수 없는 경우 호출되는 팩토리 함수입니다. 이 팩토리 함수는 인자를 받지 않으므로 list()int() 와 같은 내장 타입 생성자를 사용할 수 있습니다. 예를 들어, 초기 문자를 기반으로 단어의 인덱스를 다음과 같이 만들 수 있습니다:

    words = """Nel mezzo del cammin di nostra vita
    mi ritrovai per una selva oscura
    che la diritta via era smarrita""".lower().split()
    
    index = defaultdict(list)
    
    for w in words:
        init_letter = w[0]
        index[init_letter].append(w)
    

    index 를 출력하면 다음과 같은 결과가 나옵니다:

    defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'],
            'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'],
            'l': ['la'], 'o': ['oscura'], 'n': ['nel', 'nostra'],
            'p': ['per'], 's': ['selva', 'smarrita'],
            'r': ['ritrovai'], 'u': ['una'], 'v': ['vita', 'via']}
    

    (Guido van Rossum 기여.)

  • collections 모듈이 제공하는 양방향 큐인 deque 타입에 이제 remove(value) 메서드가 추가되었습니다. 이 메서드는 큐에서 value 가 처음 나타나는 위치를 제거하며, 값을 찾을 수 없으면 ValueError 를 발생시킵니다. (Raymond Hettinger 기여.)

  • 새로운 모듈: contextlib 모듈은 새로운 ‘with’ 문과 함께 사용하는 헬퍼 함수들을 포함합니다. 이 모듈에 대한 자세한 내용은 contextlib 모듈 섹션을 참조하십시오.

  • 새로운 모듈: cProfile 모듈은 기존 profile 모듈의 C 구현체로 훨씬 낮은 오버헤드를 가집니다. 이 모듈의 인터페이스는 profile`과 동일합니다. 예를 들어, ``cProfile.run('main()')``를 실행하여 함수를 프로파일링하거나 프로파일 데이터를 파일에 저장할 있습니다. C로 작성되었으나 :mod:!profile` 모듈의 인터페이스와 일치하지 않는 Hotshot 프로파일러가 향후 파이썬 버전에서도 계속 유지될지는 아직 알 수 없습니다. (Armin Rigo 기여.)

    또한, 프로파일러가 측정한 데이터를 분석하는 pstats 모듈이 이제 Stats 생성자에 stream 인자를 전달하여 출력을 임의의 파일 객체로 보내는 기능을 지원합니다. (Skip Montanaro 기여.)

  • 쉼표로 구분된 값(csv) 형식의 파일을 파싱하는 csv 모듈이 여러 개선 사항과 다수의 버그 수정을 거쳤습니다. 이제 csv.field_size_limit(new_limit) 함수를 호출하여 필드의 최대 바이트 크기를 설정할 수 있으며, new_limit 인수를 생략하면 현재 설정된 제한을 반환합니다. reader 클래스는 이제 원본에서 읽은 물리적 줄 수를 세는 line_num 속성을 가집니다. 레코드는 여러 개의 물리적 줄에 걸쳐 있을 수 있으므로, line_num 은 읽은 레코드의 수와 동일하지 않을 수 있습니다.

    CSV 파서가 이제 여러 줄에 걸친 인용된 필드(quoted fields)를 더욱 엄격하게 처리합니다. 이전에는 인용된 필드 내부에서 행이 끝나고 종료되는 개행 문자가 없는 경우, 결과 필드에 개행 문자가 삽입되기도 했습니다. 이러한 동작은 필드 내에 캐리지 리턴 문자가 포함된 파일을 읽을 때 문제를 일으켰으므로, 새 줄을 삽입하지 않고 필드를 그대로 반환하도록 코드가 변경되었습니다. 따라서 필드 내부에 포함된 개행 문자가 중요한 경우에는 입력 데이터를 개행 문자를 유지하는 방식으로 행 단위로 분할해야 합니다.

    (Skip Montanaro와 Andrew McNamara 기여.)

  • datetime 모듈의 datetime 클래스에 날짜 문자열을 파싱하기 위한 strptime(string, format) 메서드가 추가되었습니다 (Josh Spoerri 기여). 이 메서드는 time.strptime()time.strftime() 과 동일한 포맷 문자를 사용합니다:

    import datetime as dt
    
    ts = dt.datetime.strptime('10:13:15 2006-03-07',
                              '%H:%M:%S %Y-%m-%d')
    
  • difflib 모듈의 SequenceMatcher.get_matching_blocks() 메서드는 이제 일치하는 부분 시퀀스를 설명하는 블록의 최소 리스트를 반환함을 보장합니다. 이전에는 알고리즘이 가끔 일치하는 요소들의 블록을 두 개의 리스트 항목으로 나누기도 했습니다. (Tim Peters에 의한 개선.)

  • doctest 모듈에 예제가 아예 실행되지 않도록 하는 SKIP 옵션이 추가되었습니다. 이는 실제 테스트 케이스가 아니라 독자를 위한 사용 예제로 제공되는 코드 조각을 위한 것입니다.

    파일의 인코딩을 지정하기 위해 testfile() 함수와 DocFileSuite 클래스에 encoding 파라미터가 추가되었습니다. 이를 통해 독스트링(docstring) 내 포함된 테스트에서 비-ASCII 문자를 더 쉽게 사용할 수 있습니다. (Bjorn Tillenius 기여.)

  • email 패키지가 버전 4.0으로 업데이트되었습니다. (Barry Warsaw 기여.)

  • fileinput 모듈이 더 유연해졌습니다. 이제 유니코드 파일 이름을 지원하며, input() 함수에 기본값이 "r"mode 파라미터가 추가되어 파일을 바이너리 또는 universal newlines 모드로 열 수 있게 되었습니다. 또 다른 새 파라미터인 openhook 을 사용하면 입력 파일을 열 때 open() 이외의 함수를 사용할 수 있습니다. 파일 세트를 반복하는 동안, FileInput 객체의 새로운 fileno() 는 현재 열려 있는 파일의 파일 기술자(file descriptor)를 반환합니다. (Georg Brandl 기여.)

  • gc 모듈의 새로운 get_count() 함수는 세 가지 GC 세대에 대한 현재 수집 횟수가 포함된 3-튜플을 반환합니다. 이는 가비지 컬렉터를 위한 계정 정보로, 이 횟수가 특정 임계값에 도달하면 가비지 컬렉션 스윕이 수행됩니다. 기존 gc.collect() 함수는 이제 어떤 세대를 수거할지 지정하는 0, 1 또는 2의 선택적 generation 인자를 받습니다. (Barry Warsaw 기여.)

  • heapq 모듈의 nsmallest()nlargest() 함수가 이제 min()/max() 함수 및 sort() 메서드에서 제공되는 것과 유사한 key 키워드 파라미터를 지원합니다. 예를 들어:

    >>> import heapq
    >>> L = ["short", 'medium', 'longest', 'longer still']
    >>> heapq.nsmallest(2, L)  # 사전순으로 가장 낮은 두 요소 반환
    ['longer still', 'longest']
    >>> heapq.nsmallest(2, L, key=len)   # 길이가 가장 짧은 두 요소 반환
    ['short', 'medium']
    

    (Raymond Hettinger가 기여했습니다.)

  • itertools.islice() 함수가 이제 시작(start)과 단계(step) 인자로 None 을 허용합니다. 이를 통해 슬라이스 객체의 속성과 더 호환성이 좋아져서 다음과 같이 작성할 수 있습니다:

    s = slice(5)     # 슬라이스 객체 생성
    itertools.islice(iterable, s.start, s.stop, s.step)
    

    (Raymond Hettinger가 기여했습니다.)

  • locale 모듈의 format() 함수가 수정되었으며, format_string()currency() 라는 두 개의 새로운 함수가 추가되었습니다.

    format() 함수의 val 파라미터는 이전에 하나 이상의 %char 지정자가 나타나지 않는 한 문자열일 수 있었으나, 이제 이 파라미터는 주변 텍스트 없이 정확히 하나의 %char 지정자여야 합니다. 또한 선택적인 monetary 파라미터가 추가되었으며, 이 값이 True 인 경우 세 자리 그룹 사이에 구분 기호를 배치하는 등 화폐를 포매팅하기 위한 로케일 규칙을 사용합니다.

    여러 %char 지정자가 포함된 문자열을 포매팅하려면, format() 과 유사하게 작동하면서 임의의 텍스트와 %char 지정자를 혼합하여 지원하는 새로운 format_string() 함수를 사용하십시오.

    현재 로케일 설정에 따라 숫자를 포매팅하는 새로운 currency() 함수도 추가되었습니다.

    (Georg Brandl 기여.)

  • 사서함을 읽는 기능 외에 사서함을 수정하는 기능을 추가하기 위해 mailbox 모듈이 대폭 재작성되었습니다. mbox, MH, Maildir 를 포함하는 새로운 클래스 세트가 사서함을 읽는 데 사용되며, 메시지를 추가하는 add(message) 메서드, 메시지를 제거하는 remove(key), 사서함을 잠그거나 해제하는 lock()/unlock() 을 제공합니다. 다음 예제는 maildir 형식을 mbox 형식으로 변환합니다:

    import mailbox
    
    # 'factory=None'은 개별 메시지를 나타내는 클래스로
    # email.Message.Message를 사용합니다.
    src = mailbox.Maildir('maildir', factory=None)
    dest = mailbox.mbox('/tmp/mbox')
    
    for msg in src:
        dest.add(msg)
    

    (Gregory K. Johnson이 기여했습니다. 지원은 Google의 2005 Summer of Code를 통해 제공되었습니다.)

  • 새 모듈: msilib 모듈은 Microsoft Installer .msi 파일과 CAB 파일을 생성할 수 있게 합니다. 또한 .msi 데이터베이스를 읽는 기능이 일부 포함되어 있습니다. (Martin von Löwis가 기여했습니다.)

  • nis 모듈은 이제 nis.match()nis.maps() 함수에 domain 인자를 전달하여 시스템 기본 도메인 이외의 도메인에 접근하는 기능을 지원합니다. (Ben Bell이 기여했습니다.)

  • operator 모듈의 itemgetter()attrgetter() 함수가 이제 여러 필드를 지원합니다. 예를 들어 operator.attrgetter('a', 'b') 를 호출하면 ab 속성을 가져오는 함수를 반환합니다. 이 새로운 기능과 sort() 메서드의 key 매개변수를 결합하여 여러 필드를 사용하여 리스트를 쉽게 정렬할 수 있습니다. (Raymond Hettinger가 기여했습니다.)

  • optparse 모듈이 Optik 라이브러리 버전 1.5.1로 업데이트되었습니다. OptionParser 클래스에 도움말 메시지 뒤에 출력되는 문자열인 epilog 속성과 객체에 의해 생성된 참조 사이클을 끊는 destroy() 메서드가 추가되었습니다. (Greg Ward가 기여했습니다.)

  • os 모듈에 여러 변경 사항이 있었습니다. stat_float_times 변수가 이제 기본값으로 True로 설정되어, os.stat() 이 시간 값을 부동 소수점(float)으로 반환합니다. (이것이 os.stat() 이 초 단위 미만의 정밀한 시간을 보장한다는 의미는 아닙니다. 모든 시스템이 이러한 정밀도를 지원하지는 않습니다.)

    os.SEEK_SET, os.SEEK_CUR, 및 os.SEEK_END 상수가 추가되었습니다; 이들은 os.lseek() 함수의 매개변수입니다. 잠금을 위한 두 가지 새로운 상수는 os.O_SHLOCKos.O_EXLOCK 입니다.

    wait3()wait4() 라는 두 개의 새로운 함수가 추가되었습니다. 이들은 자식 프로세스가 종료될 때까지 대기하고 프로세스 ID와 종료 상태를 포함하는 튜플을 반환하는 waitpid() 함수와 유사하지만, wait3()wait4() 는 추가 정보를 제공합니다. wait3() 은 입력으로 프로세스 ID를 받지 않으므로 모든 자식 프로세스가 종료될 때까지 기다린 후, resource.getrusage() 함수에서 반환되는 process-id, exit-status, resource-usage 의 3개 요소가 포함된 튜플을 반환합니다. wait4(pid) 는 프로세스 ID를 받습니다. (Chad J. Schroeder가 기여했습니다.)

    FreeBSD에서 os.stat() 함수는 이제 나노초 단위의 정밀도를 가진 시간을 반환하며, 반환된 객체에는 st_genst_birthtime 이 포함됩니다. 플랫폼이 지원하는 경우 st_flags 속성도 사용할 수 있습니다. (Antti Louko와 Diego Pettenò가 기여했습니다.)

  • pdb 모듈에서 제공하는 Python 디버거가 이제 중단점(breakpoint)에 도달하여 실행이 중단될 때 실행할 명령 목록을 저장할 수 있습니다. 중단점 #1이 생성되면 commands 1 을 입력하고, 수행할 일련의 명령들을 입력한 뒤 끝에 end 를 붙여 마칩니다. 명령 목록에는 continuenext 와 같이 실행을 재개하는 명령을 포함할 수 있습니다. (Grégoire Dooms가 기여했습니다.)

  • picklecPickle 모듈은 더 이상 __reduce__() 메서드에서 None 을 반환하는 것을 허용하지 않습니다; 해당 메서드는 대신 인수들의 튜플을 반환해야 합니다. None 을 반환하는 기능은 Python 2.4에서 폐지되었으며, 이번에 완전히 제거되었습니다.

  • 패키지 탐색을 위한 다양한 유틸리티 함수를 포함하는 pkgutil 모듈이 PEP 302 임포트 후크를 지원하도록 강화되었으며, 이제 ZIP 형식 아카이브에 저장된 패키지도 작동합니다. (Phillip J. Eby가 기여했습니다.)

  • Marc-André Lemburg의 pybench 벤치마크 세트가 이제 Tools/pybench 디렉토리에 포함됩니다. pybench는 인터프리터 속도에 대해 더 상세한 측정을 제공하므로 흔히 사용되는 pystone.py 프로그램보다 개선된 버전입니다. pystone.py 와 같이 여러 작업을 수행하고 결과를 단일 숫자로 줄이는 대신, 함수 호출, 튜플 슬라이싱, 메서드 조회 및 숫자 연산과 같은 특정 작업의 소요 시간을 측정합니다.

  • pyexpat 모듈이 이제 Expat 파서 버전 2.0을 사용합니다. (Trent Mick이 기여했습니다.)

  • Queue 모듈이 제공하는 Queue 클래스에 두 개의 새로운 메서드가 추가되었습니다. join() 은 큐의 모든 항목이 검색되고 모든 처리 작업이 완료될 때까지 대기합니다. 워커 스레드는 다른 새 메서드인 task_done() 을 호출하여 항목 처리가 완료되었음을 알립니다. (Raymond Hettinger가 기여했습니다.)

  • Python 2.0 이후부터 폐지된 예전 regexregsub 모듈이 마침내 삭제되었습니다. 다른 삭제된 모듈은 다음과 같습니다: statcache, tzparse, whrandom.

  • 또한, dircmpni 와 같은 오래된 모듈을 포함하는 lib-old 디렉터리가 제거되었습니다. lib-old 는 기본 sys.path 에 포함되지 않았으므로, 프로그램에서 명시적으로 해당 디렉터리를 sys.path 에 추가하지 않는 한 이 삭제가 코드에 영향을 주지 않습니다.

  • rlcompleter 모듈이 더 이상 readline 모듈의 임포트에 의존하지 않으므로 이제 유닉스가 아닌 플랫폼에서도 작동합니다. (Robert Kiendl의 패치 적용.)

  • SimpleXMLRPCServerDocXMLRPCServer 클래스에 이제 XML-RPC 연산을 제한된 세트의 URL 경로로 제한하는 rpc_paths 속성이 추가되었습니다; 기본값은 '/''/RPC2' 만 허용하는 것입니다. rpc_pathsNone 또는 빈 튜플로 설정하면 이 경로 확인 기능이 비활성화됩니다.

  • socket 모듈이 Philippe Biondi의 패치 덕분에 리눅스에서 AF_NETLINK 소켓을 지원합니다. Netlink 소켓은 사용자 공간 프로세스와 커널 코드 간의 통신을 위한 리눅스 전용 메커니즘입니다. 이에 관한 입문 기사는 https://www.linuxjournal.com/article/7356에서 확인할 수 있습니다. 파이썬 코드에서 netlink 주소는 2개의 정수로 구성된 튜플인 (pid, group_mask) 로 표현됩니다.

    소켓 객체의 두 가지 새 메서드인 recv_into(buffer)recvfrom_into(buffer) 는 수신된 데이터를 문자열로 반환하는 대신 버퍼 프로토콜을 지원하는 객체에 저장합니다. 이는 데이터를 배열이나 메모리 매핑 파일에 직접 넣을 수 있음을 의미합니다.

    소켓 객체에 소켓의 패밀리, 타입 및 프로토콜 값을 가져오는 접근 메서드인 getfamily(), gettype(), 및 getproto() 가 추가되었습니다.

  • 새 모듈: spwd 모듈은 섀도 암호를 지원하는 시스템에서 섀도 암호 데이터베이스에 액세스하는 함수를 제공합니다.

  • struct 은 이제 포맷 문자열을 pack()unpack() 메서드를 가진 Struct 객체로 컴파일하므로 더 빠릅니다. 이는 re 모듈이 미리 컴파일된 정규 표현식 객체를 생성하도록 하는 것과 유사합니다. 여전히 모듈 레벨의 pack()unpack() 함수를 사용할 수 있으며, 이들은 Struct 객체를 생성하고 캐싱합니다. 또는 Struct 인스턴스를 직접 사용할 수도 있습니다:

    s = struct.Struct('ih3s')
    
    data = s.pack(1972, 187, 'abc')
    year, number, name = s.unpack(data)
    

    또한 pack_into(buffer, offset, v1, v2, ...)unpack_from(buffer, offset) 메서드를 사용하여 버퍼 객체와 데이터를 직접 주고받을 수 있습니다. 이를 통해 데이터가 배열이나 메모리 매핑 파일에 직접 저장될 수 있습니다.

    (Struct 객체는 Bob Ippolito가 NeedForSpeed 스프린트에서 구현했습니다. 버퍼 객체 지원은 Martin Blais가 같은 NeedForSpeed 스프린트에서 추가했습니다.)

  • 파이썬 개발자들은 2.5 개발 과정에서 CVS를 Subversion으로 전환했습니다. 정확한 빌드 버전에 대한 정보는 sys.subversion 변수((interpreter-name, branch-name, revision-range) 로 구성된 3개 요소의 튜플)에서 확인할 수 있습니다. 예를 들어, 제가 2.5를 작성할 당시 버전은 ('CPython', 'trunk', '45313:45315') 라고 보고되었습니다.

    이 정보는 C 확장 모듈에서도 Py_GetBuildInfo() 함수를 통해 사용할 수 있으며, 이 함수는 "trunk:45355:45356M, Apr 13 2006, 07:42:19" 와 같은 빌드 정보 문자열을 반환합니다. (Barry Warsaw가 기여했습니다.)

  • sys._current_frames() 라는 또 다른 새 함수는 실행 중인 모든 스레드에 대한 현재 스택 프레임을 딕셔너리로 반환하며, 이 딕셔너리는 함수가 호출되는 시점에 해당 스레드에서 활성화된 최상위 스택 프레임과 스레드 식별자를 매핑합니다. (Tim Peters가 기여했습니다.)

  • tarfile 모듈의 TarFile 클래스에 이제 아카이브의 모든 멤버를 현재 작업 디렉터리로 추출하는 extractall() 메서드가 추가되었습니다. 다른 디렉터리를 추출 대상으로 지정하거나, 아카이브의 일부 멤버만 압축을 해제하는 것도 가능합니다.

    스트림 모드로 열린 tar 파일의 압축 방식을 이제 'r|*'' 모드를 사용하여 자동 감지할 수 있습니다. (Lars Gustäbel이 기여했습니다.)

  • threading 모듈에서 이제 새 스레드를 생성할 때 사용하는 스택 크기를 설정할 수 있습니다. stack_size([*size*]) 함수는 현재 구성된 스택 크기를 반환하며, 선택적 size 매개변수를 제공하면 새로운 값을 설정합니다. 모든 플랫폼이 스택 크기 변경을 지원하는 것은 아니지만, Windows, POSIX threading, OS/2는 모두 이를 지원합니다. (Andrew MacIntyre가 기여했습니다.)

  • unicodedata 모듈이 유니코드 문자 데이터베이스 버전 4.1.0을 사용하도록 업데이트되었습니다. 일부 사양에서는 3.2.0 버전이 필요하므로, 여전히 unicodedata.ucd_3_2_0 으로 사용할 수 있습니다.

  • 새 모듈: uuid 모듈은 RFC 4122 에 따라 전역적으로 고유한 식별자(UUID)를 생성합니다. RFC는 시작 문자열, 시스템 속성 또는 순수하게 무작위로 생성되는 여러 다양한 UUID 버전을 정의합니다. 이 모듈은 UUID 클래스와 서로 다른 버전의 UUID를 생성하는 uuid1(), uuid3(), uuid4(), 및 uuid5() 라는 이름의 함수들을 포함합니다. (버전 2 UUID는 RFC 4122 에 명시되지 않았으며 이 모듈에서 지원하지 않습니다.)

    >>> import uuid
    >>> # 호스트 ID 및 현재 시간을 기반으로 UUID 생성
    >>> uuid.uuid1()
    UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
    
    >>> # 네임스페이스 UUID와 이름의 MD5 해시를 사용하여 UUID 생성
    >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
    UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
    
    >>> # 무작위 UUID 생성
    >>> uuid.uuid4()
    UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
    
    >>> # 네임스페이스 UUID와 이름의 SHA-1 해시를 사용하여 UUID 생성
    >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
    UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
    

    (Ka-Ping Yee가 기여함.)

  • weakref 모듈의 WeakKeyDictionaryWeakValueDictionary 타입이 딕셔너리에 포함된 약한 참조를 반복하는 새로운 메서드를 추가했습니다. WeakKeyDictionaryiterkeyrefs()keyrefs() 메서드가 추가되었으며, WeakValueDictionaryitervaluerefs()valuerefs() 가 추가되었습니다. (Fred L. Drake, Jr.가 기여함.)

  • webbrowser 모듈에 여러 개선 사항이 적용되었습니다. 이제 python -m webbrowser 로 실행하여 URL을 인자로 받는 스크립트로 사용할 수 있으며, 동작을 제어하기 위한 여러 스위치가 있습니다(-n 은 새 브라우저 창으로, -t 는 새 탭으로). 이를 지원하기 위해 새로운 모듈 수준 함수인 open_new()open_new_tab() 이 추가되었습니다. 이 모듈의 open() 함수는 가능한 경우 열린 창을 띄울지 여부를 나타내는 autoraise 파라미터를 지원합니다. 또한 Firefox, Opera, Konqueror, elinks와 같은 여러 브라우저가 지원 목록에 추가되었습니다. (Oleg Broytmann과 Georg Brandl이 기여함.)

  • xmlrpclib 모듈이 이제 XML-RPC 날짜 타입에 대해 datetime 객체를 반환하는 것을 지원합니다. 이 기능을 활성화하려면 loads() 함수 또는 Unmarshaller 클래스에 use_datetime=True 를 전달하십시오. (Skip Montanaro가 기여함.)

  • zipfile 모듈이 이제 ZIP64 형식을 지원하여, .zip 아카이브가 4 GiB보다 크고 개별 파일도 4 GiB보다 클 수 있습니다. (Ronald Oussoren이 기여함.)

  • zlib 모듈의 CompressDecompress 객체가 이제 내부 상태의 복사본을 생성하고 새로운 Compress 또는 Decompress 객체를 반환하는 copy() 메서드를 지원합니다. (Chris AtLee가 기여함.)

ctypes 패키지

Thomas Heller가 작성한 ctypes 패키지가 표준 라이브러리에 추가되었습니다. ctypes`를 사용하면 공유 라이브러리나 DLL의 임의 함수를 호출할 있습니다. 오래된 사용자라면 공유 라이브러리를 로드하고 해당 함수를 호출하는 기능을 제공하던 :mod:!dl` 모듈을 기억할 수도 있습니다. ctypes 패키지는 훨씬 더 세련된 기능들을 제공합니다.

공유 라이브러리나 DLL을 로드하려면 CDLL 클래스의 인스턴스를 생성하고 해당 공유 라이브러리 또는 DLL의 이름이나 경로를 제공해야 합니다. 일단 로드가 완료되면, CDLL 객체의 속성으로 접근하여 임의의 함수를 호출할 수 있습니다.

import ctypes

libc = ctypes.CDLL('libc.so.6')
result = libc.printf("Line of output\n")

Type constructors for the various C types are provided: c_int(), c_float(), c_double(), c_char_p() (equivalent to char*), and so forth. Unlike Python’s types, the C versions are all mutable; you can assign to their value attribute to change the wrapped value. Python integers and strings will be automatically converted to the corresponding C types, but for other types you must call the correct type constructor. (And I mean must; getting it wrong will often result in the interpreter crashing with a segmentation fault.)

C 함수가 메모리 영역을 수정하는 경우에 Python 문자열과 함께 c_char_p() 를 사용해서는 안 됩니다. 이는 Python 문자열이 불변(immutable)이어야 하기 때문이며, 이 규칙을 어기면 알 수 없는 버그가 발생할 수 있습니다. 수정 가능한 메모리 영역이 필요한 경우에는 create_string_buffer() 를 사용하십시오:

s = "this is a string"
buf = ctypes.create_string_buffer(s)
libc.strfry(buf)

C 함수는 기본적으로 정수를 반환하는 것으로 간주되지만, 함수 객체의 restype 속성을 설정하여 이를 변경할 수 있습니다:

>>> libc.atof('2.71828')
-1783957616
>>> libc.atof.restype = ctypes.c_double
>>> libc.atof('2.71828')
2.71828

ctypes`는 또한 ``ctypes.pythonapi` 객체로 Python의 C API 래퍼를 제공합니다. 이 객체는 인터프리터 코드를 호출할 때 락을 유지해야 하므로 함수 호출 전에 전역 인터프리터 락(GIL)을 해제하지 않습니다. PyObject* 포인터를 생성하는 py_object 타입 생성자가 있습니다. 간단한 사용법은 다음과 같습니다:

import ctypes

d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
          ctypes.py_object("abc"),  ctypes.py_object(1))
# 이제 d는 {'abc', 1}이 됩니다.

py_object() 를 사용하는 것을 잊지 마십시오. 생략할 경우 세그먼트 폴트가 발생합니다.

ctypes has been around for a while, but people still write and distribution hand-coded extension modules because you can’t rely on ctypes being present. Perhaps developers will begin to write Python wrappers atop a library accessed through ctypes instead of extension modules, now that ctypes is included with core Python.

더 보기

https://web.archive.org/web/20180410025338/http://starship.python.net/crew/theller/ctypes/

튜토리얼, 레퍼런스 및 FAQ를 포함한 표준 라이브러리 이전의 ctypes 웹 페이지.

ctypes 모듈에 대한 설명서.

ElementTree 패키지

XML 처리를 위한 Fredrik Lundh의 ElementTree 라이브러리 중 일부가 표준 라이브러리에 xml.etree 로 추가되었습니다. 제공되는 모듈은 ElementTree 1.2.6의 ElementTree, ElementPath, 및 ElementInclude 입니다. 또한 가속 모듈인 cElementTree 도 포함되어 있습니다.

이 섹션의 나머지 부분에서는 ElementTree 사용법에 대한 간략한 개요를 제공합니다. ElementTree에 대한 전체 문서는 https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm에서 확인할 수 있습니다.

ElementTree는 XML 문서를 엘리먼트 노드의 트리로 나타냅니다. 문서의 텍스트 콘텐츠는 texttail 속성으로 저장됩니다. (이는 ElementTree와 Document Object Model(DOM) 간의 주요 차이점 중 하나입니다. DOM에는 TextNode 를 포함하여 다양한 유형의 노드가 존재합니다.)

가장 일반적으로 사용되는 파싱 함수는 parse() 로, 문자열(파일 이름이 포함된 것으로 간주됨) 또는 파일과 같은 객체를 받아 ElementTree 인스턴스를 반환합니다:

from xml.etree import ElementTree as ET

tree = ET.parse('ex-1.xml')

feed = urllib.urlopen(
          'http://planet.python.org/rss10.xml')
tree = ET.parse(feed)

ElementTree 인스턴스가 있으면, getroot() 메서드를 호출하여 루트 Element 노드를 가져올 수 있습니다.

또한 문자열 리터럴을 받아 Element 노드(아닌 ElementTree)를 반환하는 XML() 함수가 있습니다. 이 함수는 XML 조각을 포함시키는 깔끔한 방법을 제공하여 XML 리터럴의 편리함에 근접합니다:

svg = ET.XML("""<svg width="10px" version="1.0">
             </svg>""")
svg.set('height', '320px')
svg.append(elem1)

각 XML 엘리먼트는 일부 딕셔너리와 유사한 액세스 방법과 리스트와 유사한 액세스 방법을 지원합니다. 딕셔너리 유사 연산은 어트리뷰트 값에 접근하는 데 사용되고, 리스트 유사 연산은 자식 노드에 접근하는 데 사용됩니다.

연산

결과

elem[n]

n번째 자식 엘리먼트를 반환합니다.

elem[m:n]

m번째부터 n번째까지의 자식 엘리먼트 리스트를 반환합니다.

len(elem)

자식 엘리먼트의 수를 반환합니다.

list(elem)

자식 엘리먼트 리스트를 반환합니다.

elem.append(elem2)

elem2 를 자식으로 추가합니다.

elem.insert(index, elem2)

지정된 위치에 elem2 을(를) 삽입합니다.

del elem[n]

n번째 자식 엘리먼트를 삭제합니다.

elem.keys()

어트리뷰트 이름 리스트를 반환합니다.

elem.get(name)

name 어트리뷰트의 값을 반환합니다.

elem.set(name, value)

name 어트리뷰트에 대한 새 값을 설정합니다.

elem.attrib

어트리뷰트를 포함하는 딕셔너리를 가져옵니다.

del elem.attrib[name]

name 어트리뷰트를 삭제합니다.

주석과 처리 명령도 Element 노드로 표현됩니다. 노드가 주석인지 또는 처리 명령인지 확인하려면:

if elem.tag is ET.Comment:
    ...
elif elem.tag is ET.ProcessingInstruction:
    ...

XML 출력을 생성하려면 ElementTree.write() 메서드를 호출해야 합니다. parse() 와 마찬가지로 문자열 또는 파일과 같은 객체를 인자로 받을 수 있습니다:

# 인코딩이 US-ASCII인 경우
tree.write('output.xml')

# 인코딩이 UTF-8인 경우
f = open('output.xml', 'w')
tree.write(f, encoding='utf-8')

(주의: 출력에 사용되는 기본 인코딩은 ASCII입니다. 엘리먼트 이름에 임의의 유니코드 문자가 포함될 수 있는 일반적인 XML 작업의 경우, ASCII는 값이 127보다 큰 문자가 하나라도 포함되면 예외를 발생시키므로 그리 유용한 인코딩이 아닙니다. 따라서 모든 유니코드 문자를 처리할 수 있는 UTF-8과 같은 다른 인코딩을 지정하는 것이 좋습니다.)

이 섹션은 ElementTree 인터페이스에 대한 부분적인 설명만 제공합니다. 자세한 내용은 패키지의 공식 문서를 참조하십시오.

hashlib 패키지

A new hashlib module, written by Gregory P. Smith, has been added to replace the md5 and sha modules. hashlib adds support for additional secure hashes (SHA-224, SHA-256, SHA-384, and SHA-512). When available, the module uses OpenSSL for fast platform optimized implementations of algorithms.

하위 호환성을 유지하기 위해 이전의 md5sha 모듈이 hashlib을 래핑한 형태로 여전히 존재합니다. 새 모듈의 인터페이스는 기존 모듈과 매우 유사하지만 완전히 동일하지는 않습니다. 가장 큰 차이점은 새로운 해싱 객체를 생성하는 생성자 함수의 이름이 다르다는 것입니다.

# 이전 버전
h = md5.md5()
h = md5.new()

# 새 버전
h = hashlib.md5()

# 이전 버전
h = sha.sha()
h = sha.new()

# 새 버전
h = hashlib.sha1()

# 기존에 사용 불가능했던 해시
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()

# 대안 형태
h = hashlib.new('md5')          # 알고리즘을 문자열로 제공

해시 객체가 한 번 생성되면, 그 메서드들은 이전과 동일합니다: update(string) 은 지정된 문자열을 현재 다이제스트 상태로 해싱하고, digest()hexdigest() 는 다이제스트 값을 바이너리 문자열 또는 16진수 문자열로 반환하며, copy() 는 동일한 다이제스트 상태를 가진 새로운 해시 객체를 반환합니다.

더 보기

hashlib 모듈에 대한 설명서.

sqlite3 패키지

SQLite 임베디드 데이터베이스의 래퍼인 pysqlite 모듈(https://www.pysqlite.org)이 표준 라이브러리에 sqlite3 패키지 이름으로 추가되었습니다.

SQLite는 별도의 서버 프로세스가 필요 없는 경량 디스크 기반 데이터베이스를 제공하는 C 라이브러리로, 비표준 SQL 질의 언어 변형을 사용하여 데이터베이스에 접근할 수 있습니다. 일부 응용 프로그램은 내부 데이터 저장소로 SQLite를 사용할 수 있으며, SQLite를 사용하여 애플리케이션을 프로토타이핑한 후 해당 코드를 PostgreSQL이나 Oracle과 같은 대형 데이터베이스로 이식하는 것도 가능합니다.

pysqlite는 Gerhard Häring이 작성했으며, PEP 249 에 기술된 DB-API 2.0 사양을 준수하는 SQL 인터페이스를 제공합니다.

Python 소스를 직접 컴파일하는 경우, 소스 트리에는 SQLite 코드가 포함되지 않고 래퍼 모듈만 포함된다는 점에 유의하십시오. Python을 컴파일하기 전에 SQLite 라이브러리와 헤더를 설치해야 하며, 빌드 과정에서 필요한 헤더가 준비되면 해당 모듈이 컴파일됩니다.

이 모듈을 사용하려면 먼저 데이터베이스를 나타내는 Connection 객체를 생성해야 합니다. 여기서 데이터는 /tmp/example 파일에 저장됩니다:

conn = sqlite3.connect('/tmp/example')

You can also supply the special name :memory: to create a database in RAM.

일단 Connection 을 얻으면, Cursor 객체를 생성하고 그 외의 execute() 메서드를 호출하여 SQL 명령을 수행할 수 있습니다:

c = conn.cursor()

# Create table
c.execute('''create table stocks
(date text, trans text, symbol text,
 qty real, price real)''')

# Insert a row of data
c.execute("""insert into stocks
          values ('2006-01-05','BUY','RHAT',100,35.14)""")

일반적으로 SQL 연산 시 파이썬 변수의 값을 사용해야 합니다. 파이썬의 문자열 연산을 사용하여 쿼리를 구성해서는 안 되는데, 이는 보안에 취약하며 프로그램이 SQL 인젝션 공격에 노출될 수 있기 때문입니다.

대신 DB-API의 매개변수 치환을 사용하십시오. 값을 사용할 위치에 ? 를 자리 표시자로 넣고, 커서의 execute() 메서드의 두 번째 인자로 값들의 튜플을 제공합니다. (다른 데이터베이스 모듈은 %s 또는 :1 과 같은 다른 자리 표시자를 사용할 수도 있습니다.) 예를 들면:

# Never do this -- insecure!
symbol = 'IBM'
c.execute("... where symbol = '%s'" % symbol)

# Do this instead
t = (symbol,)
c.execute('select * from stocks where symbol=?', t)

# Larger example
for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
          ('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
          ('2006-04-06', 'SELL', 'IBM', 500, 53.00),
         ):
    c.execute('insert into stocks values (?,?,?,?,?)', t)

SELECT 문을 실행한 후 데이터를 가져오려면 커서를 이터레이터로 취급하거나, 커서의 fetchone() 메서드를 호출하여 일치하는 단일 행을 가져오거나, fetchall() 을 호출하여 일치하는 행들의 리스트를 가져올 수 있습니다.

이 예제는 이터레이터 형태를 사용합니다:

>>> c = conn.cursor()
>>> c.execute('select * from stocks order by price')
>>> for row in c:
...    print row
...
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)
(u'2006-04-06', u'SELL', u'IBM', 500, 53.0)
(u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
>>>

SQLite에서 지원하는 SQL 방언에 대한 자세한 정보는 https://www.sqlite.org를 참조하십시오.

더 보기

https://www.pysqlite.org

pysqlite 웹 페이지.

https://www.sqlite.org

SQLite 웹 페이지; 문서에는 지원되는 SQL 방언에 대한 구문과 사용 가능한 데이터 형식이 설명되어 있습니다.

sqlite3 모듈의 공식 문서입니다.

PEP 249 - 데이터베이스 API 사양 2.0

Marc-André Lemburg가 작성한 PEP입니다.

wsgiref 패키지

Web Server Gateway Interface(WSGI) v1.0은 웹 서버와 파이썬 웹 애플리케이션 사이의 표준 인터페이스를 정의하며, PEP 333 에 기술되어 있습니다. wsgiref 패키지는 WSGI 사양의 참조 구현체입니다.

이 패키지에는 WSGI 애플리케이션을 실행하는 기본 HTTP 서버가 포함되어 있으며, 이 서버는 디버깅에 유용하지만 운영 환경용으로 설계되지는 않았습니다. 서버 설정은 몇 줄의 코드로 가능합니다:

from wsgiref import simple_server

wsgi_app = ...

host = ''
port = 8000
httpd = simple_server.make_server(host, port, wsgi_app)
httpd.serve_forever()

더 보기

https://web.archive.org/web/20160331090247/http://wsgi.readthedocs.org/en/latest/

WSGI 관련 리소스를 위한 중앙 웹사이트입니다.

PEP 333 - 파이썬 웹 서버 게이트웨이 인터페이스 v1.0

Phillip J. Eby가 작성한 PEP입니다.

빌드 및 C API 변경사항

Python 빌드 프로세스 및 C API의 변경 사항은 다음과 같습니다:

  • 파이썬 소스 트리는 복잡한 마이그레이션 절차를 통해 CVS에서 Subversion으로 변환되었으며, 이는 Martin von Löwis의 감독 아래 결함 없이 수행되었습니다. 이 절차는 PEP 347 으로 개발되었습니다.

  • 소스 코드 분석 도구인 Prevent를 판매하는 기업인 Coverity가 파이썬 소스 코드 검토 결과를 제공했습니다. 분석 결과 약 60개의 버그가 발견되어 신속하게 수정되었습니다. 많은 버그는 오류 처리 코드에서 자주 발생하는 참조 횟수(refcounting) 문제였습니다. 통계 수치는 https://scan.coverity.com에서 확인 가능합니다.

  • C API에서 가장 큰 변화는 PEP 353 을 통해 발생했으며, 이는 인터프리터가 int 대신 Py_ssize_t 타입 정의를 사용하도록 수정합니다. 이 변경 사항에 대한 논의는 앞선 섹션인 PEP 353: 인덱스 유형으로 ssize_t 사용 을 참조하십시오.

  • 바이트코드 컴파일러의 설계가 크게 변경되어 더 이상 파스 트리(parse tree)를 순회하며 바이트코드를 생성하지 않습니다. 대신 파스 트리는 추상 구문 트리(AST)로 변환되며, 이 추상 구문 트리를 순회하여 바이트코드를 생성합니다.

    파이썬 코드는 내장 함수인 compile() 을 사용하고 flags 매개변수의 값으로 _ast.PyCF_ONLY_AST 를 지정하여 AST 객체를 얻을 수 있습니다:

    from _ast import PyCF_ONLY_AST
    ast = compile("""a=0
    for i in range(10):
        a += i
    """, "<string>", 'exec', PyCF_ONLY_AST)
    
    assignment = ast.body[0]
    for_loop = ast.body[1]
    

    아직 AST 코드에 대한 공식 문서는 작성되지 않았으나, PEP 339 에서 관련 설계를 다룹니다. 코드를 학습하려면 Parser/Python.asdl 의 다양한 AST 노드 정의를 읽어보십시오. 파이썬 스크립트가 이 파일을 읽어 Include/Python-ast.h 에 일련의 C 구조체 정의를 생성합니다. Include/pythonrun.h 에 정의된 PyParser_ASTFromString()PyParser_ASTFromFile() 은 파이썬 소스를 입력으로 받아 내용을 나타내는 AST의 루트를 반환하며, 이 AST는 PyAST_Compile() 을 통해 코드 객체로 변환될 수 있습니다. 더 자세한 정보가 필요하면 소스 코드를 읽어본 후 python-dev에서 질문하십시오.

    AST 코드는 Jeremy Hylton의 관리하에 개발되었으며, Brett Cannon, Nick Coghlan, Grant Edwards, John Ehresman, Kurt Kaiser, Neal Norwitz, Tim Peters, Armin Rigo, Neil Schemenauer(알파벳 순) 및 PyCon과 같은 컨퍼런스의 여러 AST 스프린트 참여자들이 구현했습니다.

  • PyCon DC 2005 강연에서 처음 설명된 Evan Jones의 obmalloc 패치가 적용되었습니다. 파이썬 2.4는 256K 크기의 아레나에 작은 객체를 할당했지만 아레나를 해제하지 않았습니다. 이 패치를 통해 파이썬은 아레나가 비어 있을 때 이를 해제합니다. 그 결과 일부 플랫폼에서 많은 객체를 할당한 후 삭제할 때 파이썬의 메모리 사용량이 실제로 줄어들고 메모리가 운영체제로 반환될 수 있습니다. (Evan Jones가 구현하고 Tim Peters가 재구성했습니다.)

    이 변경으로 인해 확장 모듈은 메모리 할당 시 더욱 주의를 기울여야 합니다. 파이썬 API는 여러 종류의 메모리 할당 함수를 포함하며, 이들은 패밀리로 그룹화되어 있습니다. 예를 들어, PyMem_Malloc(), PyMem_Realloc(), 및 PyMem_Free() 는 원시 메모리를 할당하는 하나의 패밀리이며, PyObject_Malloc(), PyObject_Realloc(), 및 PyObject_Free() 는 파이썬 객체 생성을 위해 사용되는 다른 패밀리입니다.

    이전에는 이러한 서로 다른 패밀리들이 모두 플랫폼의 malloc()free() 함수로 귀결되었습니다. 이는 실수로 PyMem 함수로 메모리를 할당하고 PyObject 함수로 해제하더라도 문제가 되지 않았음을 의미합니다. obmalloc에 대한 2.5 버전의 변경으로 이제 이 패밀리들은 서로 다르게 동작하며, 불일치가 발생할 경우 세그멘테이션 오류(segfault)가 발생할 가능성이 높습니다. 파이썬 2.5를 사용하여 C 확장 모듈을 주의 깊게 테스트해야 합니다.

  • 내장 셋(set) 타입이 이제 공식 C API를 갖게 되었습니다. 새로운 세트를 생성하려면 PySet_New()PyFrozenSet_New() 을, 요소를 추가하거나 제거하려면 PySet_Add()PySet_Discard() 를, 세트의 상태를 확인하려면 PySet_Contains()PySet_Size() 를 호출하십시오. (Raymond Hettinger가 기여했습니다.)

  • C 코드는 이제 Py_GetBuildInfo() 함수를 호출하여 파이썬 인터프리터의 정확한 리비전 정보를 얻을 수 있으며, 이 함수는 "trunk:45355:45356M, Apr 13 2006, 07:42:19" 와 같은 빌드 정보 문자열을 반환합니다. (Barry Warsaw가 기여했습니다.)

  • 현재 파일 내에서만 사용하는 C 함수임을 나타내기 위해 두 개의 새로운 매크로를 사용할 수 있으며, 이를 통해 더 빠른 호출 규약을 적용할 수 있습니다. Py_LOCAL 은 함수가 지정된 형식 의 값을 반환한다고 선언하고 빠른 호출 한정자를 사용합니다. Py_LOCAL_INLINE 도 동일하게 작동하며 추가로 해당 함수를 인라인화하도록 요청합니다. 만약 python.h 포함 전에 매크로 PY_LOCAL_AGGRESSIVE 가 정의되면 모듈에 대해 더 공격적인 최적화 세트가 활성화됩니다. 이러한 최적화가 실제로 코드를 더 빠르게 만드는지 확인하려면 벤치마크 결과를 확인해야 합니다. (Fredrik Lundh가 NeedForSpeed 스프린트에서 기여했습니다.)

  • PyErr_NewException(name, base, dict) 이 이제 base 인자로 베이스 클래스의 튜플을 받아들일 수 있습니다. (Georg Brandl가 기여했습니다.)

  • 경고를 발생시키는 PyErr_Warn() 함수는 이제 PyErr_WarnEx(category, message, stacklevel) 로 대체되어 권장되지 않습니다. 이 함수는 해당 함수와 호출자 사이의 스택 프레임 수를 지정할 수 있게 해줍니다. stacklevel 이 1이면 PyErr_WarnEx() 를 호출하는 함수, 2면 그 위의 함수이며 이런 식으로 이어집니다. (Neal Norwitz가 추가했습니다.)

  • CPython 인터프리터는 여전히 C로 작성되었지만, 이제 오류 없이 C++ 컴파일러로 컴파일할 수 있습니다. (Anthony Baxter, Martin von Löwis, Skip Montanaro가 구현했습니다.)

  • PyRange_New() 함수가 제거되었습니다. 이 함수는 문서화된 적이 없고 코어 코드에서 사용된 적도 없으며, 오류 검사가 매우 느슨했습니다. 드문 경우로 여러분의 확장 모듈에서 이 함수를 사용하는 경우에는 다음과 같은 방식으로 대체할 수 있습니다:

    range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll",
                                  start, stop, step);
    

포트별 변경 사항

  • MacOS X (10.3 이상): 모듈의 동적 로딩이 이제 macOS 전용 함수 대신 dlopen() 함수를 사용합니다.

  • MacOS X: 해석기를 PowerPC와 Intel 프로세서 모두에서 실행 가능한 유니버설 바이너리로 컴파일하는 configure 스크립트에 --enable-universalsdk 옵션이 추가되었습니다. (Ronald Oussoren 기여; bpo-2573.)

  • Windows: 확장 모듈의 파일명 확장자로 .dll`을 이상 지원하지 않습니다. 이제 :file:.pyd`만이 검색되는 유일한 파일명 확장자입니다.

Python 2.5로 이식하기

이 섹션은 코드 변경이 필요할 수 있는 이전에 설명된 변경 사항을 나열합니다:

  • 이제 모듈의 기본 인코딩은 ASCII입니다. 모듈에 8비트 문자가 포함된 문자열 리터럴이 있으면서 인코딩 선언이 없는 경우 이제는 구문 오류(syntax error)가 발생합니다. Python 2.4에서는 이 경우 경고만 발생하고 구문 오류는 발생하지 않았습니다.

  • 이전에는 제너레이터의 gi_frame 속성이 항상 프레임(frame) 객체였습니다. PEP 342: 새로운 제너레이터 기능 섹션에 기술된 PEP 342 변경 사항으로 인해, 이제 gi_frameNone 이 될 수 있습니다.

  • 기본 ASCII 인코딩을 사용하여 유니코드(Unicode)로 변환할 수 없는 8비트 문자열과 유니코드 문자열을 비교하려고 할 때 새로운 경의인 UnicodeWarning 이 발생합니다. 이전에는 이러한 비교 시 UnicodeDecodeError 예외가 발생했습니다.

  • Library: csv 모듈이 여러 줄에 걸친 따옴표 필드에 대해 더 엄격하게 처리합니다. 파일의 필드 내에 줄바꿈 문자가 포함된 경우, 입력 데이터는 줄바꿈 문자를 유지하는 방식으로 줄 단위로 분할되어야 합니다.

  • Library: locale 모듈의 format() 함수는 이전에는 하나 이상의 %char 지정자가 나타나지 않는 한 어떤 문자열도 허용했습니다. Python 2.5에서는 인자가 주변 텍스트 없이 정확히 하나의 %char 지정자여야 합니다.

  • Library: picklecPickle 모듈은 더 이상 __reduce__() 메서드에서 None 을 반환하는 것을 허용하지 않으며, 대신 인자들의 튜플을 반환해야 합니다. 또한 이 모듈들은 더 이상 사용이 중단된 bin 키워드 매개변수를 허용하지 않습니다.

  • Library: SimpleXMLRPCServerDocXMLRPCServer 클래스에 이제 XML-RPC 작업을 제한된 URL 경로 세트로 제한하는 rpc_paths 속성이 추가되었습니다. 기본값은 '/''/RPC2' 만 허용하는 것입니다. rpc_pathsNone 또는 빈 튜플로 설정하면 이 경로 확인이 비활성화됩니다.

  • C API: 많은 함수가 이제 64비트 머신에서 더 많은 데이터를 처리할 수 있도록 int 대신 Py_ssize_t 를 사용합니다. 확장 코드는 경고를 방지하고 64비트 머신을 지원하기 위해 동일한 변경을 수행해야 할 수도 있습니다. 이 변경 사항에 대한 논의는 앞선 PEP 353: 인덱스 유형으로 ssize_t 사용 섹션을 참조하십시오.

  • C API: obmalloc 변경으로 인해 PyMem_*``와 ``PyObject_* 함수군을 혼합하여 사용하는 데 주의해야 합니다. 한 가족의 *_Malloc``으로 할당된 메모리는 반드시 해당 가족의 ``*_Free 함수로 해제해야 합니다.

감사의 말

저자는 이 문서의 여러 초안에 대해 제안, 수정 및 도움을 제공해 준 다음 사람들에게 감사를 표합니다: Georg Brandl, Nick Coghlan, Phillip J. Eby, Lars Gustäbel, Raymond Hettinger, Ralf W. Grosse-Kunstleve, Kent Johnson, Iain Lowe, Martin von Löwis, Fredrik Lundh, Andrew McNamara, Skip Montanaro, Gustavo Niemeyer, Paul Prescod, James Pryor, Mike Rovner, Scott Weikart, Barry Warsaw, Thomas Wouters.

분실물 보관소