Python 2.1의 새로운 기능¶
- 저자:
A.M. Kuchling
소개¶
이 문서는 Python 2.1의 새로운 기능들을 설명합니다. 2.1에 포함된 변화가 Python 2.0만큼 많지는 않지만 여전히 흥미로운 요소들이 있습니다. 2.1은 파이썬 개선 제안(PEP)을 통해 제작된 첫 번째 릴리스로, 대부분의 주요 변경 사항에는 더 상세한 문서와 설계 근거를 제공하는 관련 PEP가 포함되어 있습니다. 이 문서는 모든 신기능을 완벽하게 다루려 하기보다는 파이썬 프로그래머들을 위한 개요를 제공합니다. 특정 기능에 대한 자세한 정보는 Python 2.1 공식 문서나 해당 PEP를 참조하십시오.
최근 파이썬 개발 팀의 목표 중 하나는 출시 주기를 단축하여 6개월에서 9개월마다 새로운 버전을 내놓는 것이었습니다. 2.1은 이 가속화된 속도에 맞춰 출시된 첫 번째 버전으로, 2.0 최종 버전 발표 3개월 후인 1월에 첫 알파 버전이 공개되었습니다.
Python 2.1의 최종 릴리스는 2001년 4월 17일에 이루어졌습니다.
PEP 227: 중첩 스코프¶
Python 2.1에서 가장 큰 변화는 파이썬의 스코핑 규칙입니다. Python 2.0에서는 어떤 시점에서든 변수 이름을 찾기 위해 최대 세 가지 네임스페이스(로컬, 모듈 수준, 빌트인)만 사용되었습니다. 이는 많은 사람들에게 직관적인 기대와 다르기 때문에 당혹감을 주곤 했습니다. 예를 들어, 중첩된 재귀 함수 정의가 작동하지 않는 경우가 있습니다:
def f():
...
def g(value):
...
return g(value-1) + 1
...
함수 g() 은 항상 NameError 예외를 발생시킵니다. 왜냐하면 이름 g 이 로컬 네임스페이스나 모듈 수준 네임스페이스 어디에도 바인딩되지 않았기 때문입니다. 실제 상황에서 이것이 큰 문제는 아니지만(내부 함수를 이런 방식으로 재귀적으로 정의하는 경우가 얼마나 자주 있겠습니까?), 이 구조는 lambda 표현식의 사용을 더 번거롭게 만들었으며 이는 실무적으로 문제가 되었습니다. lambda 를 사용하는 코드에서는 종종 인수의 기본값으로 지역 변수를 전달하여 이를 복사하는 방식을 볼 수 있습니다.
def find(self, name):
"Return list of any entries equal to 'name'"
L = filter(lambda x, name=name: x == name,
self.list_attribute)
return L
그 결과, 강한 기능적 스타일로 작성된 파이썬 코드의 가독성이 크게 저하되었습니다.
Python 2.1의 가장 중요한 변화는 이 문제를 해결하기 위해 정적 스코핑(static scoping)이 언어에 추가되었다는 점입니다. 첫 번째 효과로, 위의 예제에서 name=name 이라는 기본 인자가 더 이상 필요하지 않습니다. 간단히 말해, 특정 함수 내에서 변수 이름에 값이 할당되지 않은 경우(할당문이나 def, class, 또는 import 구문에 의해), 해당 변수에 대한 참조는 둘러싼 스코프의 로컬 네임스페이스에서 검색됩니다. 규칙에 대한 더 자세한 설명과 구현 방식에 대한 분석은 PEP에서 확인할 수 있습니다.
이 변화는 동일한 변수 이름이 모듈 수준과 하위 함수 정의를 포함하는 함수의 로컬 변수로 모두 사용되는 코드에서 일부 호환성 문제를 일으킬 수 있습니다. 그러나 이러한 코드는 처음부터 읽기 상당히 혼란스러웠을 것이므로 실제 발생 가능성은 낮아 보입니다.
이 변화의 부작용 중 하나는 특정 조건에서 함수 스코프 내의 from module import * 및 exec 구문이 금지되었다는 것입니다. 파이썬 참조 매뉴얼은 항상 from module import * 가 모듈의 최상위 수준에서만 허용된다고 명시해 왔지만, CPython 인터프리터는 이전까지 이를 강제한 적이 없었습니다. 중첩된 스코프 구현의 일부로, 파이썬 소스를 바이트코드로 변환하는 컴파일러는 포함된 스코프(containing scope)의 변수에 접근하기 위해 다른 코드를 생성해야 합니다. from module import * 와 exec 는 컴파일 시점에 알 수 없는 이름을 로컬 네임스페이스에 추가하므로, 컴파일러가 이를 판단하는 것을 불가능하게 만듭니다. 따라서 함수 내에 자유 변수가 포함된 함수 정의나 lambda 표현식이 있는 경우, 컴파일러는 SyntaxError 예외를 발생시켜 이를 알립니다.
앞선 설명을 조금 더 명확하게 설명하기 위한 예시입니다:
x = 1
def f():
# 다음 줄은 구문 오류입니다
exec 'x=2'
def g():
return x
exec 문이 포함된 4행은 구문 오류입니다. 왜냐하면 exec 가 g() 에 의해 접근되어야 하는 값과 이름이 같은 새로운 로컬 변수 x 를 정의하게 되기 때문입니다.
대부분의 파이썬 코드에서 exec 는 거의 사용되지 않으므로(사용되더라도 대개 설계가 부실하다는 신호입니다), 이것이 큰 제한 사항이 되지는 않을 것입니다.
호환성에 대한 우려로 인해 중첩된 스코프는 점진적으로 도입되었습니다. Python 2.1에서는 기본으로 활성화되지 않지만, PEP 236 에 기술된 대로 미래(future) 문을 사용하여 모듈 내에서 활성화할 수 있습니다. (상세한 내용은 다음 섹션의 PEP 236 설명을 참조하십시오.) Python 2.2부터는 중첩된 스코프가 기본값이 되어 끌 수 없게 되지만, 사용자들은 이를 도입하며 발생하는 문제를 해결할 충분한 기간(Python 2.1의 전체 생애 주기)을 갖게 될 것입니다.
더 보기
- PEP 227 - 정적 중첩 스코프(Statically Nested Scopes)
Jeremy Hylton이 작성하고 구현했습니다.
PEP 236: __future__ 지시어¶
중첩된 스코프에 대한 반응은 2.1 출시로 인해 코드가 망가질 수 있다는 광범위한 우려였으며, 이는 파이썬 개발자들이 더 보수적인 접근 방식을 취하게 만들 정도로 강력했습니다. 이 방식은 버전 N에서 선택적으로 활성화할 수 있는 기능을 도입하고, 버전 N+1에서 이를 필수 사항으로 만드는 관례를 포함합니다.
이 구문은 예약된 모듈 이름인 __future__`를 사용하는 ``from...import` 문을 사용합니다. 다음 문을 통해 중첩된 스코프를 활성화할 수 있습니다:
from __future__ import nested_scopes
이것은 일반적인 import 문처럼 보이지만 그렇지 않습니다. 이러한 퓨처(future) 문이 들어갈 수 있는 위치에는 엄격한 규칙이 있습니다. 이들은 반드시 모듈의 상단에 위치해야 하며, 어떠한 파이썬 코드나 일반적인 import 문보다 앞서야 합니다. 이는 그러한 문들이 파이썬 바이트코드 컴파일러가 코드를 파싱하고 바이트코드를 생성하는 방식에 영향을 줄 수 있기 때문에, 바이트코드가 생성되는 모든 구문보다 먼저 나타나야 하기 때문입니다.
더 보기
- PEP 236 - Back to the
__future__ Tim Peters가 작성하고 Jeremy Hylton이 주로 구현했습니다.
PEP 207: 풍부한 비교(Rich Comparisons)¶
이전 버전에서 사용자 정의 클래스 및 확장 유형에 대한 비교 구현 지원은 매우 단순했습니다. 클래스는 두 개의 인스턴스를 받아 0(같음), +1(큼), -1(작음)만 반환할 수 있는 __cmp__() 메서드를 구현할 수 있었으며, 이 메서드는 예외를 발생시키거나 불리언 외의 값을 반환할 수 없었습니다. Numeric Python 사용자들은 이 모델이 너무 약하고 제한적이라고 느꼈는데, 이는 수치 계산 프로그램에서 두 행렬의 요소별 비교를 수행하고 각 요소에 대한 결과가 포함된 행렬을 반환하는 것이 훨씬 유용하기 때문입니다. 만약 두 행렬의 크기가 다르면 비교 시 오류를 알리는 예외를 발생시켜야 합니다.
Python 2.1에서는 이러한 요구 사항을 지원하기 위해 풍부한 비교(rich comparisons)가 추가되었습니다. 이제 파이썬 클래스에서 <, <=, >, >=, ==, != 연산을 각각 오버로드할 수 있습니다. 새로운 매직 메서드 이름은 다음과 같습니다.
작동 방식 |
메서드 이름 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
(이 매직 메서드들은 해당 포트란 연산자인 .LT., .LE. 등의 이름을 따서 명명되었습니다. 수치 프로그래머라면 이 이름들에 매우 익숙할 것이므로 기억하기 쉬울 것입니다.)
이 매직 메서드들은 각각 method(self, other) 형태이며, 여기서 self 는 연산자의 왼쪽에 있는 객체이고 other 는 오른쪽에 있는 객체입니다. 예를 들어, A < B 라는 표현식은 A.__lt__(B) 를 호출합니다.
이 매직 메서드들은 Boolean, 행렬(matrix), 리스트 또는 다른 어떤 파이썬 객체도 반환할 수 있습니다. 또는 비교가 불가능하거나 일관성이 없거나 무의미한 경우 예외를 발생시킬 수도 있습니다.
내장된 cmp(A,B) 함수는 리치 비교(rich comparison) 메커니즘을 사용할 수 있으며, 이제 어떤 비교 연산을 사용할지 지정하는 선택적 인자를 하나 받습니다. 이 인자는 "<", "<=", ">", ">=", "==" 또는 "!=" 중 하나의 문자열로 제공됩니다. 세 번째 선택적 인수 없이 호출하면 cmp() 는 이전 파이썬 버전과 마찬가지로 -1, 0, 또는 +1만 반환하며, 그렇지 않으면 적절한 메서드를 호출하여 어떤 파이썬 객체든 반환할 수 있습니다.
C 프로그래머에게도 유의미한 변경 사항이 있습니다. 타입 객체에 새로운 슬롯인 tp_richcmp 가 추가되었고 주어진 풍부한 비교를 수행하기 위한 API가 제공됩니다. 여기서 C API 전체를 다루지는 않지만, 관련 기능의 전체 목록은 PEP 207 또는 2.1 버전의 C API 문서를 참조하십시오.
더 보기
- PEP 207 - 풍부한 비교(Rich Comparisons)
Guido van Rossum이 작성하였으며, David Ascher의 이전 연구를 기반으로 하여 Guido van Rossum에 의해 구현되었습니다.
PEP 230: 경고 프레임워크(Warning Framework)¶
파이썬이 존재한 10년 동안 여러 개의 쓸모없어진 모듈과 기능들이 축적되었습니다. 특정 기능을 제거해도 안전한지 판단하기는 어렵습니다. 해당 기능을 사용하는 코드가 얼마나 되는지 알 방법이 없기 때문입니다. 어쩌면 아무도 사용하지 않을 수도 있고, 혹은 아주 많은 프로그램이 이를 의존하고 있을 수도 있습니다. 오래된 기능을 보다 체계적으로 제거하기 위해 경고 프레임워크가 추가되었습니다. 파이썬 개발자가 특정 기능을 제거하고자 할 때, 해당 기능은 다음 버전의 파이썬에서 먼저 경고를 발생시킵니다. 그 후 그다음 파이썬 버전에서 해당 기능을 삭제하게 되며, 사용자는 한 번의 릴리스 주기에 걸쳐 해당 기능을 사용하는 코드를 수정할 시간을 갖게 됩니다.
Python 2.1은 이 체계에서 사용될 경고 프레임워크를 추가합니다. 경고를 발행하고 표시되지 않기를 원하는 경고를 걸러내는 함수를 제공하는 warnings 모듈이 추가되었습니다. 타사(third-party) 모듈 또한 더 이상 지원하지 않는 오래된 기능을 폐지(deprecate)할 때 이 프레임워크를 사용할 수 있습니다.
예를 들어, Python 2.1에서 regex 모듈은 폐지되었으므로 이를 임포트하면 경고가 출력됩니다:
>>> import regex
__main__:1: DeprecationWarning: the regex module
is deprecated; please use the re module
>>>
경고는 warnings.warn() 함수를 호출하여 발행할 수 있습니다:
warnings.warn("feature X no longer supported")
첫 번째 매개변수는 경고 메시지이며, 추가적인 선택적 매개변수를 사용하여 특정 경고 카테고리를 지정할 수 있습니다.
특정 경고를 비활성화하기 위해 필터를 추가할 수 있습니다. 메시지나 모듈 이름에 정규표현식 패턴을 적용하여 경고를 억제할 수 있습니다. 예를 들어, regex 모듈을 사용하는 프로그램이 있지만 당장 이를 re 모듈로 변환할 시간이 없는 경우에 유용합니다. 해당 경고는 다음과 같이 호출하여 억제할 수 있습니다:
import warnings
warnings.filterwarnings(action = 'ignore',
message='.*regex module is deprecated',
category=DeprecationWarning,
module = '__main__')
이것은 __main__ 모듈에서 발생한 DeprecationWarning 클래스의 경고에만 적용되는 필터를 추가하며, regex 모듈의 폐지에 관한 메시지와 일치하는 정규표현식을 적용하여 해당 경고를 무시하게 합니다. 또한 경고는 한 번만 출력하거나, 문제가 되는 코드가 실행될 때마다 출력하거나, 프로그램이 중단되도록 예외로 변환할 수도 있습니다(물론 예외가 일반적인 방식으로 처리되지 않는 경우에 한함).
경고를 발행하기 위한 기능들이 파이썬의 C API에도 추가되었습니다. 자세한 내용은 PEP 230 또는 파이썬 API 문서를 참조하십시오.
PEP 229: 새로운 빌드 시스템¶
파이썬을 컴파일할 때 사용자는 다양한 추가 모듈을 활성화하기 위해 Modules/Setup 파일을 직접 수정해야 했습니다. 기본 설정은 상당히 적었으며 대부분의 유닉스 플랫폼에서 빌드 가능한 모듈로 제한되어 있었습니다. 이는 특히 많은 기능을 포함하는 리눅스와 같은 유닉스 플랫폼에서 파이썬 설치 시 사용 가능한 모든 유용한 모듈이 포함되지 않는다는 것을 의미했습니다.
Python 2.0은 확장 기능을 배포하고 설치하기 위한 모듈 세트인 Distutils를 추가했습니다. Python 2.1에서는 Distutils를 사용하여 표준 라이브러리의 대부분의 확장 모듈을 컴파일하며, 현재 머신에서 지원되는 모듈을 자동으로 감지합니다. 이를 통해 파이썬 설치가 더 쉽고 더 많은 기능을 갖추게 될 것으로 기대됩니다.
모듈을 활성화하기 위해 Modules/Setup 파일을 수정하는 대신, 파이썬 소스 배포의 상위 디렉터리에 있는 setup.py 스크립트가 빌드 시점에 실행되어 시스템의 모듈과 헤더 파일을 조사하고 활성화 가능한 모듈을 찾아냅니다. 만약 특정 모듈이 Modules/Setup`에 구성되어 있다면, :file:`setup.py 스크립트는 해당 모듈을 컴파일하려고 시도하지 않고 Modules/Setup 파일의 내용을 따릅니다. 이를 통해 특정 플랫폼에서 필요한 특수한 명령줄 플래그나 라이브러리를 지정할 수 있습니다.
빌드 메커니즘에 대한 또 다른 중대한 변화로, Neil Schemenauer는 구조를 재구성하여 파이썬이 상위 디렉터리 및 Python/, Parser/, Objects/, Modules/ 하위 디렉터리 각각에 있는 Makefile 대신 재귀적이지 않은 단일 Makefile을 사용하도록 했습니다. 이로 인해 파이썬 빌드 속도가 향상되었고, Makefile 수정 작업도 더 명확하고 단순해졌습니다.
더 보기
- PEP 229 - 파이썬 빌드에 Distutils 사용
A.M. Kuchling이 작성하고 구현했습니다.
PEP 205: 약한 참조(Weak References)¶
weakref 모듈을 통해 사용할 수 있는 약한 참조(Weak references)는 파이썬 프로그래머의 도구 모음에서 작지만 유용한 새로운 데이터 유형입니다.
객체에 대한 참조를 저장하는 것(예: 딕셔너리나 리스트에 저장)은 해당 객체를 계속 생존하게 만드는 부수 효과가 있습니다. 이러한 동작이 바람직하지 않은 몇 가지 특정 사례가 있는데, 가장 흔한 경우는 객체 캐시이며, 다른 하나는 트리와 같은 데이터 구조에서의 순환 참조입니다.
예를 들어, 함수 인자와 그 결과값을 딕셔너리에 저장하여 다른 함수 f(x) 의 결과를 캐싱하는 메모이제이션(memoizing) 기능을 가진 함수를 생각해 보십시오:
_cache = {}
def memoize(x):
if _cache.has_key(x):
return _cache[x]
retval = f(x)
# 결과 객체 캐시
_cache[x] = retval
return retval
이 버전은 정수와 같은 단순한 경우에는 작동하지만 부수 효과가 있습니다. _cache 딕셔너리가 반환값에 대한 참조를 보유하므로 파이썬 프로세스가 종료되고 정리될 때까지 해당 값들이 해제되지 않습니다. 정수의 경우에는 눈에 띄지 않지만, 만약 f() 가 객체나 많은 메모리를 차지하는 데이터 구조를 반환한다면 문제가 될 수 있습니다.
약한 참조는 객체가 더 이상 필요하지 않을 때까지 살아있게 하지 않으면서 캐시를 구현하는 방법을 제공합니다. 만약 어떤 객체에 대한 접근이 약한 참조를 통해서만 이루어진다면, 그 객체는 해제될 것이고 약한 참조는 해당 객체가 더 이상 존재하지 않음을 나타내게 됩니다. 객체 obj 에 대한 약한 참조는 wr = weakref.ref(obj) 를 호출하여 생성됩니다. 참조되는 객체는 약한 참조를 마치 함수인 것처럼 호출함으로써 얻을 수 있습니다: wr(). 이는 참조된 객체를 반환하거나, 해당 객체가 더 이상 존재하지 않는 경우 None 을 반환합니다.
캐시에 약한 참조(weak reference)를 저장함으로써 캐시가 객체를 계속 유지하지 않는 memoize() 함수를 작성할 수 있습니다.
_cache = {}
def memoize(x):
if _cache.has_key(x):
obj = _cache[x]()
# 약한 참조 객체가 여전히 존재하는지 확인
# 존재하면 반환
if obj is not None: return obj
retval = f(x)
# 약한 참조 캐싱
_cache[x] = weakref.ref(retval)
return retval
weakref 모듈은 약한 참조처럼 동작하는 프록시 객체를 생성할 수도 있습니다. 즉, 프록시 객체에 의해서만 참조되는 객체는 메모리에서 해제되지만, 프록시를 통해 객체에 접근할 때 명시적인 호출 없이도 객체가 존재하는 한 모든 연산을 투명하게 전달합니다. 만약 해당 객체가 메모리에서 해제된 상태에서 프록시를 사용하려고 하면 weakref.ReferenceError 예외가 발생합니다.
proxy = weakref.proxy(obj)
proxy.attr # obj.attr과 동일
proxy.meth() # obj.meth()와 동일
del obj
proxy.attr # 약한 참조 오류 발생
더 보기
- PEP 205 - 약한 참조
Fred L. Drake, Jr.가 작성하고 구현함.
PEP 232: 함수 속성¶
파이썬 2.1부터 함수에 임의의 정보를 추가할 수 있습니다. 기존에는 __doc__ 속성이 함수에 정보를 추가하는 유일한 방법이었기 때문에, 많은 이들이 독스트링을 사용하여 함수 및 메서드에 대한 정보를 담아왔습니다. 예를 들어, Zope 웹 애플리케이션 서버에서는 독스트링이 있으면 공개 접근이 가능한 것으로 표시하고, John Aycock의 SPARK 파싱 프레임워크에서는 독스트링에 분석할 BNF 문법의 일부를 포함했습니다. 이러한 중복 활용은 독스트링의 원래 목적이 함수의 설명(documentation)을 담는 것이기 때문에 좋지 않은 사례입니다. 예를 들어 Zope에서 독스트링을 이런 식으로 사용하면 내부용 함수를 제대로 문서화할 수 없게 됩니다.
이제 일반적인 파이썬 구문을 사용하여 함수에 임의의 속성을 설정하고 가져올 수 있습니다:
def f(): pass
f.publish = 1
f.secure = 1
f.grammar = "A ::= B (C D)*"
속성을 포함하는 딕셔너리는 함수의 __dict__ 로 접근할 수 있습니다. 클래스 인스턴스의 __dict__ 속성과 달리, 함수에서는 __dict__ 에 새로운 딕셔너리를 할당할 수 있습니다. 다만 새 값은 일반 파이썬 딕셔너리로 제한되며, 매핑처럼 작동하는 다른 객체나 UserDict 인스턴스로 설정할 수는 없습니다.
더 보기
- PEP 232 - 함수 속성
Barry Warsaw가 작성하고 구현함.
PEP 235: 대소 문자를 구분하지 않는 플랫폼에서 모듈 임포트하기¶
일부 운영 체제는 대소 문자를 구분하지 않는 파일 시스템을 사용하며, MacOS와 Windows가 대표적인 예입니다. 이러한 시스템에서는 원본의 대소 문자가 보존되더라도 FILE.PY``와 ``file.py 같은 파일 이름을 구별하는 것이 불가능합니다.
In Python 2.1, the import statement will work to simulate case-sensitivity
on case-insensitive platforms. Python will now search for the first
case-sensitive match by default, raising an ImportError if no such file
is found, so import file will not import a module named FILE.PY.
Case-insensitive matching can be requested by setting the PYTHONCASEOK
environment variable before starting the Python interpreter.
PEP 217: 대화형 디스플레이 후크¶
파이썬 인터프리터를 대화형으로 사용할 때, 명령의 출력은 내장된 repr() 함수를 통해 표시됩니다. 파이썬 2.1에서는 sys.displayhook() 변수를 호출 가능한 객체로 설정하여 repr() 대신 실행되게 할 수 있습니다. 예를 들어, 이를 특별한 프리티 프린팅(pretty-printing) 함수로 설정할 수 있습니다:
>>> # 재귀적 데이터 구조 생성
... L = [1,2,3]
>>> L.append(L)
>>> L # 파이썬 기본 출력 표시
[1, 2, 3, [...]]
>>> # 디스플레이 함수로 pprint.pprint() 사용
... import sys, pprint
>>> sys.displayhook = pprint.pprint
>>> L
[1, 2, 3, <Recursion on list with id=135143996>]
>>>
더 보기
- PEP 217 - 대화형 사용을 위한 디스플레이 후크
Moshe Zadka가 작성하고 구현함.
PEP 208: 새로운 강제 변환 모델¶
C 수준에서 수행되는 수치 강제 변환 방식이 대폭 수정되었습니다. 이는 파이썬 C 확장 모듈 작성자에게만 해당하며, 이로 인해 수치 연산을 지원하는 확장 유형을 더 유연하게 작성할 수 있게 됩니다.
확장 유형은 이제 PyTypeObject 구조에 타입 플래그 Py_TPFLAGS_CHECKTYPES 를 설정하여 새로운 강제 변환 모델을 지원함을 알릴 수 있습니다. 이러한 확장 유형에서 수치 슬롯 함수는 더 이상 두 개의 인자가 동일한 유형이라고 가정하지 않으며, 대신 서로 다른 유형의 인자가 전달될 수 있고 이에 따라 자체적인 내부 강제 변환을 수행할 수 있습니다. 만약 슬롯 함수에 처리할 수 없는 유형이 전달되면, Py_NotImplemented 싱글톤 값에 대한 참조를 반환하여 실패를 알릴 수 있습니다. 그러면 다른 쪽 타입의 수치 함수가 시도되며 해당 기능이 가능할 수도 있습니다. 만약 다른 쪽 타입도 Py_NotImplemented 를 반환하면 TypeError 가 발생합니다. 파이썬으로 작성된 수치 메서드 역시 Py_NotImplemented 를 반환할 수 있으며, 이 경우 인터프리터는 해당 메서드가 없는 것처럼 동작합니다(예: TypeError 를 발생시키거나 다른 객체의 수치 메서드를 시도함).
더 보기
- PEP 208 - 강제 변환 모델 재구성
Neil Schemenauer가 작성하고 구현했으며, Marc-André Lemburg의 이전 연구를 기반으로 합니다. C 수준에서 수치 연산이 처리되는 방식에 대한 상세한 내용을 이해하려면 이 문서를 읽어보십시오.
PEP 241: 파이썬 패키지의 메타데이터¶
파이썬 사용자들의 공통된 불만은 존재하는 모든 파이썬 모듈에 대한 단일 카탈로그가 없다는 것입니다. www.vex.net/parnassus/ 에서 제공되던 T. Middleton의 Vaults of Parnassus(2009년 2월 은퇴, 인터넷 아카이브 웨이크백 머신 <https://web.archive.org/web/20090130140102/http://www.vex.net/parnassus/> 에서 확인 가능)가 가장 큰 파이썬 모듈 카탈로그였으나, Vaults에 소프트웨어를 등록하는 것은 선택 사항이었고 많은 사람이 이를 수행하지 않았습니다.
이 문제를 해결하기 위한 첫 번째 단계로, Distutils의 sdist 명령을 사용하여 패키징된 파이썬 소프트웨어에는 이름, 버전, 저자(카탈로그 용어로는 메타데이터)와 같은 정보를 포함하는 PKG-INFO 파일이 포함됩니다. PEP 241 은 PKG-INFO 파일에 포함될 수 있는 모든 필드 목록을 제공합니다. 사람들이 파이썬 2.1을 사용하여 소프트웨어를 패키징하기 시작함에 따라 점점 더 많은 패키지에 메타데이터가 포함될 것이며, 이를 통해 자동화된 카탈로그 시스템을 구축하고 실험할 수 있게 될 것입니다. 이러한 경험을 바탕으로 더욱 훌륭한 카탈로그를 설계하고 파이썬 2.2에 대한 지원을 구축할 수도 있을 것입니다. 예를 들어, Distutils의 sdist 및 bdist_* 명령은 패키지를 카탈로그 서버에 자동으로 업로드하는 upload 옵션을 지원할 수 있습니다.
이전 파이썬 버전을 사용하는 사용자들을 위한 새로운 Distutils 릴리스가 제공되므로, 파이썬 2.1을 사용하지 않더라도 PKG-INFO 를 포함하는 패키지를 만들기 시작할 수 있습니다. Distutils 버전 1.0.2에는 PEP 241 에 기술된 변경 사항과 다양한 버그 수정 및 기능 개선이 포함되어 있습니다. 해당 버전은 Distutils SIG의 https://www.python.org/community/sigs/current/distutils-sig/에서 확인할 수 있습니다.
개선 및 신규 모듈¶
Ka-Ping Yee가 두 개의 새로운 모듈을 기여했습니다. 실행 중인 파이썬 코드에 대한 정보를 가져오는
inspect.py와 독스트링을 대화형으로 HTML 또는 텍스트로 변환하는pydoc.py입니다. 추가 기능으로, 이제 자동으로 설치되는Tools/scripts/pydoc은 파이썬 모듈, 패키지 또는 클래스 이름이 주어지면pydoc.py를 사용하여 문서를 표시합니다. 예를 들어,pydoc xml.dom을 실행하면 다음과 같이 출력됩니다:Python Library Documentation: package xml.dom in xml NAME xml.dom - W3C Document Object Model implementation for Python. FILE /usr/local/lib/python2.1/xml/dom/__init__.pyc DESCRIPTION The Python mapping of the Document Object Model is documented in the Python Library Reference in the section on the xml.dom package. This package contains the following modules: ...
pydoc에는 Tk 기반의 대화형 도움말 브라우저도 포함되어 있습니다.pydoc은 금방 중독될 수 있으니 한번 사용해 보세요!표준 라이브러리에 두 가지 서로 다른 유닛 테스트 모듈이 추가되었습니다. Tim Peters가 기여한
doctest모듈은 독스트링에 내장된 예제를 실행하고 결과를 예상 출력과 비교하는 방식의 테스트 프레임워크를 제공합니다. Steve Purcell이 기여한 PyUnit은 JUnit에서 영감을 받은 유닛 테스트 프레임워크로, 이는 다시 Kent Beck의 Smalltalk 테스트 프레임워크를 개작한 것입니다. PyUnit에 대한 더 자세한 정보는 https://pyunit.sourceforge.net/ 에서 확인할 수 있습니다.difflib모듈에는 두 시퀀스를 비교하고 한 시퀀스를 다른 시퀀스로 변환하는 데 필요한 변경 사항을 계산하는SequenceMatcher클래스가 포함되어 있습니다. 예를 들어, 이 모듈은 Unix diff 프로그램과 유사한 도구를 작성하는 데 사용될 수 있으며, 실제로 샘플 프로그램인Tools/scripts/ndiff.py는 그러한 스크립트를 작성하는 방법을 보여줍니다.ncurses 및 SYSV curses의 일부인 패널 라이브러리의 래퍼인
curses.panel은 Thomas Gellekum이 기여했습니다. 패널 라이브러리는 윈도우에 깊이(depth)라는 추가 기능을 제공합니다. 윈도우는 깊이 순서에서 더 높거나 낮게 이동할 수 있으며, 패널 라이브러리는 패널이 겹치는 위치와 어떤 섹션이 보이는지 판단합니다.PyXML 패키지는 파이썬 2.0 이후 여러 번의 릴리스를 거쳤으며, 파이썬 2.1에는 업데이트된 버전의
xml패키지가 포함되어 있습니다. 주목할 만한 변경 사항으로는 Expat 1.2 및 이후 버전에 대한 지원, Expat 구문 분석기가 파이썬에서 지원하는 모든 인코딩의 파일을 처리할 수 있는 기능, 그리고 SAX, DOM 및minidom모듈에 대한 다양한 버그 수정 등이 있습니다.Ping은 처리되지 않은 예외를 처리하기 위한 또 다른 후크를 기여했습니다.
sys.excepthook()을 호출 가능한 객체로 설정할 수 있습니다. 예외가 어떤try…except블록에서도 잡히지 않으면 해당 예외는sys.excepthook()으로 전달되며, 그곳에서 원하는 처리를 수행할 수 있습니다. 제9회 파이썬 컨퍼런스에서 Ping은 이 후크를 활용한 애플리케이션을 시연했습니다. 이는 단순히 스택 프레임만 나열하는 것이 아니라 각 프레임에 대한 함수 인수와 지역 변수까지 포함된 확장 트레이스백을 출력하는 기능입니다.time모듈의 여러 함수(예:asctime(),localtime())는 에포크(epoch) 이후 경과된 시간을 초 단위로 포함하는 부동 소수점 인수를 필요로 합니다. 이 함수들은 현재 시각을 다루기 위해 가장 자주 사용되므로, 부동 소수점 인자를 선택 사항으로 변경했습니다. 값이 제공되지 않으면 현재 시각이 사용됩니다. 예를 들어, 로그 파일 항목은 일반적으로 현재 시각을 포함하는 문자열이 필요합니다. Python 2.1에서는 기존에 길게 작성해야 했던time.asctime(time.localtime(time.time()))대신 간단하게time.asctime()을 사용할 수 있습니다.이 변경 사항은 Thomas Wouters가 제안하고 구현했습니다.
ftplib모듈은 이제 기본적으로 패시브 모드로 파일을 가져옵니다. 패시브 모드가 방화벽 뒤에서 작동할 가능성이 더 높기 때문입니다. 이 요청은 Debian 버그 추적 시스템에서 전달되었으며, 다른 Debian 패키지들이ftplib을 사용하여 파일을 가져올 때 방화벽 뒤에서 제대로 작동하지 않는 문제가 발생했기 때문입니다. Netscape가 기본적으로 패시브 모드를 사용하고 관련 불만이 거의 없으므로 이 변경이 문제를 일으킬 가능성은 낮지만, 만약 패시브 모드가 귀하의 애플리케이션이나 네트워크 설정에 적합하지 않다면 FTP 객체에서set_pasv(0)을 호출하여 패시브 모드를 비활성화할 수 있습니다.Grant Edwards의 기여로
socket모듈에 로우(raw) 소켓 액세스 지원이 추가되었습니다.pstats모듈은 이제 Python 프로그램의 타이밍 프로파일을 표시하기 위한 간단한 대화형 통계 브라우저를 포함하며, 해당 모듈이 스크립트로 실행될 때 호출됩니다. Eric S. Raymond가 기여했습니다.현재 호출 스택에서 특정 프레임 객체를 반환하는 구현체 의존적 함수인
sys._getframe([depth])가 추가되었습니다.sys._getframe()은 호출 스택의 맨 위에 있는 프레임을 반환하며, 선택적 정수 인자 depth 가 제공되면 스택 상단에서 depth 만큼 아래에 있는 프레임을 반환합니다. 예를 들어,sys._getframe(1)은 호출자의 프레임 객체를 반환합니다.이 함수는 CPython에만 존재하며, Jython이나 .NET 구현체에는 포함되어 있지 않습니다. 디버깅 용도로만 사용하고 실제 운영 코드에 포함하지 않도록 주의하십시오.
기타 변경 사항 및 수정¶
짧은 출시 주기로 인해 Python 2.1에서는 비교적 적은 수의 소규모 변경만 이루어졌습니다. CVS 변경 로그를 검색한 결과 적용된 패치가 117개, 수정된 버그가 136건으로 확인되었으나 두 수치 모두 실제보다 적게 측정되었을 가능성이 높습니다. 주요 변경 사항은 다음과 같습니다.
시스템의
malloc()보다 빠르고 메모리 오버헤드가 적은 전용 객체 할당자를 선택적으로 사용할 수 있습니다. 이 할당자는 C의malloc()함수를 사용하여 대규모 메모리 풀을 확보한 다음, 이 풀에서 더 작은 메모리 요청을 처리합니다. configure 스크립트에--with-pymalloc옵션을 제공하여 활성화할 수 있으며, 상세 구현 내용은Objects/obmalloc.c를 참조하십시오.C 확장 모듈의 작성자는 객체 할당자가 활성화된 상태에서 코드를 테스트해야 합니다. 일부 잘못된 코드가 실행 중에 코어 덤프를 발생시키며 작동을 중단시킬 수 있기 때문입니다. Python C API에는 기존에 C 라이브러리의
malloc()및free()의 단순한 별칭으로 사용되던 많은 메모리 할당 함수들이 포함되어 있어, 서로 맞지 않는 함수를 실수로 호출하더라도 오류가 눈에 띄지 않았습니다. 객체 할당자가 활성화되면 이러한 함수들은 더 이상malloc()및free()의 별칭이 아니므로, 메모리 해제를 위해 잘못된 함수를 호출하면 코어 덤프가 발생합니다. 예를 들어,PyMem_New를 사용하여 할당된 메모리는free()가 아닌PyMem_Del()을 사용하여 해제해야 합니다. Python에 포함된 일부 모듈이 이 문제로 인해 수정되었으며, 다른 타사 모듈들도 동일한 문제를 겪을 가능성이 높습니다.객체 할당자는 Vladimir Marangozov가 기여했습니다.
라인 중심의 파일 I/O 속도에 대한 불만이 많고, 이것이 종종 단순한 성능 벤치마크로 활용되었기 때문에 처리 속도를 개선했습니다. 이에 따라 파일 객체의
readline()메서드를 훨씬 빠르게 재작성했습니다. 정확한 속도 향상 정도는 C 라이브러리의getc()가 얼마나 느렸느냐에 따라 플랫폼마다 다르지만, 약 66% 정도이며 특정 운영 체제에서는 훨씬 더 빠를 수 있습니다. Tim Peters가 comp.lang.python의 논의를 바탕으로 이 변경을 위한 대부분의 벤치마킹과 코딩을 담당했습니다.Jeff Epler가 기여한 파일 객체를 위한 새로운 모듈과 메서드가 추가되었습니다. 새로 추가된
xreadlines`는 기존의 :func:()!xrange` 내장 기능과 유사합니다.xreadlines`은 반복(iteration)만 지원하는 불투명 시퀀스 객체를 반환하며, 매 반복마다 한 줄씩 읽습니다. 이는 기존의 :meth:()!readlines` 메서드처럼 파일 전체를 메모리로 불러오지 않습니다. 다음과 같이 사용할 수 있습니다:for line in sys.stdin.xreadlines(): # ... 각 줄에 대해 무언가를 수행 ... ...
라인 I/O 변경 사항에 대한 자세한 논의는 https://mail.python.org/pipermail/python-dev/2001-January/의 2001년 1월 1일~15일자 python-dev 요약에서 확인하십시오.
딕셔너리의 내용을 파괴적으로 반복(iterate)할 수 있도록 하는 새로운 메서드인
popitem()이 추가되었습니다. 이 방식은 대규모 딕셔너리에서 모든 키나 값을 포함하는 리스트를 생성할 필요가 없으므로 더 빠를 수 있습니다.모듈은 이제
__all__속성에 임포트될 이름 목록을 정의함으로써from module import *를 사용할 때 어떤 이름을 가져올지 제어할 수 있습니다. 자주 발생하는 불만 사항 중 하나는, 모듈이sys나string과 같은 다른 모듈을 임포트할 경우from module import *가 이를 해당 모듈의 네임스페이스에 추가하는 것입니다. 이를 해결하려면__all__에 공개(public) 명칭만 나열하면 됩니다:# 공개 명칭 목록 __all__ = ['Database', 'open']
이 패치의 더 엄격한 버전이 처음에는 Ben Wolfson에 의해 제안되고 구현되었으나, python-dev 논의를 거쳐 조금 더 완화된 최종 버전이 채택되었습니다.
문자열에
repr`을 적용할 때 이전에는 인쇄 불가능한 문자에 8진수 이스케이프를 사용했습니다(예: 줄바꿈은 `()’012’). 이는 파이썬의 C 기반 조상으로부터 남겨진 흔적이었으나, 오늘날 8진수는 실질적인 활용도가 매우 낮습니다. Ka-Ping Yee는 8진수 대신 16진수 이스케이프를 사용하고 적절한 문자에 대해 ``\n,\t,\r이스케이프를 사용하는 방식을 제안했으며, 이러한 새로운 형식을 구현했습니다.컴파일 시점에 감지된 구문 오류에 대해 이제 에러가 발생한 파일 이름과 줄 번호를 포함하는 예외를 발생시킵니다. 이는 Jeremy Hylton이 수행한 컴파일러 재구조화로 인한 유용한 부수 효과입니다.
다른 모듈을 임포트하는 C 확장 프로그램이
PyImport_ImportModule()을 사용하도록 변경되었으며, 이는 설치된 모든 임포트 훅(hook)을 사용함을 의미합니다. C 코드에서 다른 모듈을 임포트해야 하는 타사(third-party) 확장 프로그램에도 이 방식을 권장합니다.Fredrik Lundh의 도움으로 유니코드 문자 데이터베이스의 크기가 340KB 추가로 줄어들었습니다.
몇 가지 새로운 포트가 추가되었습니다: MacOS X (Steven Majewski), Cygwin (Jason Tishler), RISCOS (Dietmar Schwertberger), Unixware 7 (Billy G. Allie).
또한 목록화하기에는 너무 많은 양의 일상적인 소규모 버그 수정, 미세한 메모리 누수 해결, 도큐스트링 편집 및 기타 조정이 포함되어 있습니다. 자세한 내용은 CVS 로그를 확인하십시오.
감사합니다¶
저자는 이 문서의 다양한 초안에 대해 조언을 제공해 준 다음 분들에게 감사를 표합니다: Graeme Cross, David Goodger, Jay Graves, Michael Hudson, Marc-André Lemburg, Fredrik Lundh, Neil Schemenauer, Thomas Wouters.