Python 2.1의 새로운 기능¶
- 저자:
A.M. Kuchling
소개¶
이 문서는 Python 2.1의 새로운 기능을 설명합니다. 2.1 버전에서 2.0보다 많은 변화는 없지만, 여전히 몇 가지 즐거운 놀라움이 있습니다. 2.1은 PEP(Python Enhancement Proposals) 사용을 통해 이끌어지는 첫 번째 릴리스이기 때문에, 대부분의 상당한 변경 사항에는 더 완전한 문서와 변경 사항에 대한 설계 근거를 제공하는 PEP가 수반됩니다. 이 문서는 새로운 기능을 완전히 문서화하려 하기보다, 파이썬 프로그래머들을 위한 새로운 기능에 대한 개요를 제공하기만 합니다. 특별히 관심 있는 새로운 기능에 대한 더 자세한 내용은 Python 2.1 문서를 참조하거나, 해당 PEP를 참조하십시오.
파이썬 개발팀의 최근 목표 중 하나는 새 릴리스의 속도를 높여, 6개월에서 9개월마다 새로운 릴리스를 내는 것이었습니다. 2.1은 이 더 빠른 속도로 출시된 첫 번째 릴리스로, 2.0의 최종 버전이 출시된 3개월 후에 첫 번째 알파가 등장했습니다.
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 코드의 가독성은 크게 손상됩니다.
Python 2.1에서 가장 중요한 변경 사항은 이 문제를 해결하기 위해 언어에 정적 범위(static scoping)가 추가되었다는 것입니다. 첫 번째 효과로, name=name 기본 인수는 더 이상 위의 예시에서 필요하지 않습니다. 간단히 말해, 주어진 변수 이름이 함수 내에서 값으로 할당되지 않은 경우(할당, 또는 def, class, 또는 import 문을 통한 할당), 변수 참조는 외부 범위의 지역 네임스페이스에서 찾아집니다. 규칙에 대한 더 자세한 설명과 구현 분석은 PEP에서 찾을 수 있습니다.
이러한 변경 사항은 모듈 레벨과 함수 내부의 로컬 변수로 동일한 변수 이름이 사용되는 코드에 일부 호환성 문제를 일으킬 수 있습니다. 하지만 기본적으로 이런 코드는 애초에 읽기가 꽤 혼란스러웠을 테니, 그럴 가능성은 낮아 보입니다.
이러한 변경 사항의 하나의 부작용은 특정 조건 하에서 from module import * 및 exec 문장이 함수 스코프 안에서 불법적이 되었다는 것입니다. Python 참조 매뉴얼은 항상 from module import * 가 모듈의 최상위 레벨에서만 유효하다고 말했지만, CPython 인터프리터는 이전에 이를 강제한 적이 없습니다. 중첩된 스코프를 구현하는 과정에서, Python 소스 코드를 바이트코드로 변환하는 컴파일러는 포함하는 스코프의 변수에 접근하기 위해 다른 코드를 생성해야 합니다. from module import * 및 exec 는 컴파일 시간에 알 수 없는 지역 네임스페이스에 이름을 추가하기 때문에 컴파일러가 이를 판단하는 것을 불가능하게 만듭니다. 따라서 함수가 자유 변수(free variables)를 가진 함수 정의나 lambda 표현식을 포함하면, 컴파일러는 SyntaxError 예외를 발생시켜 이를 플래그합니다.
앞선 설명을 조금 더 명확히 하기 위해, 여기 예제가 있습니다:
x = 1
def f():
# 다음 줄은 구문 오류입니다.
exec 'x=2'
def g():
return x
exec 문이 포함된 라인 4는 x 의 값이 g() 에 의해 접근되어야 할 새로운 로컬 변수를 정의하므로 구문 오류입니다.
이는 큰 제한 사항은 아닐 것입니다. 왜냐하면 exec 는 대부분의 Python 코드에서 거의 사용되지 않으며 (사용되는 경우에도, 이는 종종 나쁜 디자인의 신호일 뿐이기 때문입니다).
Compatibility concerns have led to nested scopes being introduced gradually; in Python 2.1, they aren’t enabled by default, but can be turned on within a module by using a future statement as described in PEP 236. (See the following section for further discussion of PEP 236.) In Python 2.2, nested scopes will become the default and there will be no way to turn them off, but users will have had all of 2.1’s lifetime to fix any breakage resulting from their introduction.
더 보기
- PEP 227 - 정적 중첩 스코프(Statically Nested Scopes)
작성 및 구현자: Jeremy Hylton.
PEP 236: __future__ 지시문¶
중첩 스코프에 대한 반응은 2.1 릴리스로 인한 코드 파괴의 위험에 대한 광범위한 우려였으며, 이는 Pythoneer들이 보다 보수적인 접근 방식을 취하게 만들 만큼 강력했습니다. 이 접근 방식은 N 릴리스에서 선택적 기능을 활성화하는 규칙을 도입하는 것으로 구성되며, 이는 N+1 릴리스에서 필수적이게 됩니다.
이 구문은 예약된 모듈 이름 __future__`를 사용하는 ``from...import` 문을 사용합니다. 중첩 스코프는 다음 문으로 활성화할 수 있습니다:
from __future__ import nested_scopes
일반적인 import 문처럼 보이지만 그렇지 않습니다. 이러한 미래 문을 넣을 수 있는 곳에 엄격한 규칙이 있습니다. 모듈의 맨 위에만 있을 수 있으며, 모든 Python 코드나 일반적인 import 문보다 앞서야 합니다. 그 이유는 이러한 문이 Python 바이트코드 컴파일러가 코드를 구문 분석하고 바이트코드를 생성하는 방식에 영향을 줄 수 있기 때문에, 바이트코드가 생성될 결과를 가져오는 모든 문보다 앞서야 하기 때문입니다.
PEP 207: 풍부한 비교¶
이전 버전에서 Python은 사용자 정의 클래스 및 확장 자료형에 대한 비교 구현 지원이 상당히 단순했습니다. 클래스는 두 인스턴스를 받는 __cmp__() 메서드를 구현할 수 있었으며, 동일하면 0만을 반환하거나 다르면 +1 또는 -1을 반환할 수 있었습니다. 이 메서드는 예외를 발생시키거나 부울 값 이외의 다른 값을 반환할 수 없었습니다. Numeric Python 사용자는 이 모델이 너무 약하고 제한적이라고 자주 느꼈는데, 숫자 계산 프로그램에서 Numeric Python이 사용되는 경우, 두 행렬에 대한 요소별 비교를 수행하고 각 요소에 대한 주어진 비교 결과를 포함하는 행렬을 반환하는 것이 더 유용했기 때문입니다. 두 행렬의 크기가 다르면, 오류를 신호하기 위해 비교는 예외를 발생시킬 수 있어야 합니다.
Python 2.1에서는 이러한 필요를 지원하기 위해 rich comparison이 추가되었습니다. 이제 Python 클래스는 <, <=, >, >=, ==, != 연산자 각각을 개별적으로 오버로드할 수 있습니다. 새로운 매직 메서드 이름은 다음과 같습니다:
작동 방식 |
메서드 이름 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
(매직 메서드는 상응하는 Fortran 연산자 .LT., .LE. 등에서 이름이 따왔습니다. 숫자 프로그래머들은 이러한 이름에 익숙할 가능성이 높으며 쉽게 기억할 수 있을 것입니다.)
이러한 매직 메서드들은 모두 method(self, other) 형태이며, 여기서 self 는 연산자의 좌항에 있는 객체이고, other 는 우항에 있는 객체가 됩니다. 예를 들어, A < B 표현식은 A.__lt__(B) 를 호출하게 됩니다.
이러한 매직 메서드들은 부울 값, 행렬, 리스트 또는 기타 다른 Python 객체를 포함하여 무엇이든 반환할 수 있습니다. 또는 비교가 불가능하거나, 일관성이 없거나, 기타 의미가 없을 경우 예외를 발생시킬 수도 있습니다.
내장 cmp(A, B) 함수는 rich comparison 메커니즘을 사용할 수 있으며, 이제 사용할 비교 연산자를 지정하는 선택적 인수를 받습니다. 이는 "<", "<=", ">", ">=", "==", 또는 "!=" 문자열 중 하나로 제공됩니다. 선택적 세 번째 인수 없이 호출되는 경우, :func:`!cmp`는 이전 버전의 Python처럼 -1, 0, 또는 +1만 반환합니다. 그렇지 않은 경우, 적절한 메서드를 호출하고 임의의 Python 객체를 반환할 수 있습니다.
C 프로그래머들에게도 흥미로운 변화가 있습니다. 자료형 객체에 새로운 슬롯인 tp_richcmp 이 생겼고, 주어진 rich comparison을 수행하기 위한 API가 생겼습니다. 여기서는 C API를 다루지는 않겠습니다만, 관련 함수 전체 목록은 PEP 207 또는 2.1의 C API 문서에서 참조하시기 바랍니다.
더 보기
- PEP 207 - rich 비교
Guido van Rossum이 작성했으며, David Ascher의 초기 작업에 크게 기반하고 Guido van Rossum이 구현했습니다.
PEP 230: 경고 프레임워크¶
Python은 10년의 존재 기간 동안 많은 수의 구식 모듈과 기능을 축적해 왔습니다. 어떤 기능이 제거하기 안전한지 알기 어렵습니다. 왜냐하면 코드가 얼마나 많이 사용하는지 알 방법이 없기 때문입니다. — 어쩌면 어떤 프로그램도 그 기능에 의존하지 않을 수도 있고, 어쩌면 많은 프로그램이 의존할 수도 있습니다. 오래된 기능을 더 구조화된 방식으로 제거할 수 있도록 경고 프레임워크가 추가되었습니다. Python 개발자들이 기능을 제거하고 싶을 때, 먼저 다음 버전의 Python에서 경고를 발생시킵니다. 그다음 Python 버전에서 해당 기능을 제거할 수 있으며, 사용자들은 이제 오래된 기능의 사용을 제거할 완전한 릴리스 주기가 주어집니다.
Python 2.1은 이 체계에서 사용되는 경고 프레임워크를 추가합니다. 경고를 발생시키고 표시하고 싶지 않은 경고를 걸러내는 기능을 제공하는 warnings 모듈을 추가합니다. 서드파티 모듈도 이 프레임워크를 사용하여 더 이상 지원하기를 원하지 않는 오래된 기능을 폐기할 수 있습니다.
예를 들어, 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__')
이것은 DeprecationWarning 클래스로부터 트리거된 __main__ 모듈의 경고에만 적용되는 필터를 추가하며, regex 모듈이 사용 중단되었음에 대한 메시지 패턴만 일치시키는 정규 표현식을 적용하여 이러한 경고를 무시하게 합니다. 경고는 또한 한 번만 인쇄하거나, 문제가 되는 코드가 실행될 때마다 인쇄하거나, 예외로 전환되어 프로그램을 중지시키는 것도 가능합니다 (물론 예외가 정상적으로 포착되는 경우는 제외합니다).
경고를 발행하기 위해 Python C API에도 함수가 추가되었습니다. 자세한 내용은 PEP 230 또는 Python의 API 문서를 참조하십시오.
PEP 229: 새로운 빌드 시스템¶
Python을 컴파일할 때, 사용자는 여러 추가 모듈을 활성화하기 위해 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을 사용하게 되었습니다. 이는 파이썬 빌드를 더 빠르게 만들고 Makefiles를 해킹하는 작업도 더 명확하고 간단하게 만듭니다.
더 보기
- PEP 229 - Distutils를 사용하여 Python 빌드하기
A.M. Kuchling이 작성하고 구현했습니다.
PEP 205: 약한 참조¶
weakref 모듈을 통해 사용할 수 있는 약한 참조는 파이썬 프로그래머의 도구 상자에서 사소하지만 유용한 새로운 데이터 유형입니다.
객체에 대한 참조를 저장하는 것(예: 딕셔너리나 리스트에)은 그 객체를 영구적으로 살아있게 하는 부작용을 가집니다. 이러한 동작이 바람직하지 않은 몇 가지 특정 경우가 있는데, 객체 캐시가 가장 흔하며, 또 다른 경우는 트리와 같은 데이터 구조에서 순환 참조입니다.
예를 들어, 함수의 인수를 저장하고 그 결과를 딕셔너리에 저장하여 다른 함수 f(x) 의 결과를 캐시하는 메모이제이션 함수를 고려해 보겠습니다.
_cache = {}
def memoize(x):
if _cache.has_key(x):
return _cache[x]
retval = f(x)
# 캐시된 객체 저장
_cache[x] = retval
return retval
이 버전은 정수와 같은 간단한 경우에 작동하지만, 사이드 이펙트가 있습니다. _cache 딕셔너리는 반환 값에 대한 참조를 보유하므로, 파이썬 프로세스가 종료되고 정리될 때까지 이들은 절대 해제되지 않습니다. 정수의 경우 눈에 띄지 않지만, :func:`!f`가 객체나 많은 메모리를 차지하는 데이터 구조를 반환하는 경우 문제가 될 수 있습니다.
약한 참조는 객체가 생존하는 시간을 초과하여 객체를 유지하지 않는 캐시를 구현하는 방법을 제공합니다. 객체가 약한 참조를 통해서만 액세스 가능하면, 객체는 해제되고 약한 참조는 해당 객체가 더 이상 존재하지 않음을 나타냅니다. 객체 obj 에 대한 약한 참조는 wr = weakref.ref(obj) 를 호출하여 생성됩니다. 참조되는 객체는 약한 참조를 함수처럼 호출함으로써 반환됩니다: wr() . 객체는 참조된 객체 또는 객체가 더 이상 존재하지 않는 경우 None 을 반환합니다.
이것은 약한 참조를 캐시에 저장함으로써 객체를 생존하게 유지하지 않는 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 모듈은 또한 약한 참조처럼 동작하는 프록시 객체(proxy objects)를 생성할 수 있게 합니다. 프록시 객체에 의해서만 참조되는 객체는 해제되지만, 객체를 검색하기 위해 명시적인 호출이 필요하지 않고, 객체가 여전히 존재하는 한 프록시는 모든 작업에 투명하게 전달합니다. 객체가 해제되면, 프록시를 사용하려고 시도할 때 weakref.ReferenceError 예외가 발생합니다.
proxy = weakref.proxy(obj)
proxy.attr # obj.attr와 동일
proxy.meth() # obj.meth()와 동일
del obj
proxy.attr # weakref.ReferenceError 발생
더 보기
- PEP 205 - 약한 참조
Fred L. Drake, Jr.가 작성하고 구현함.
PEP 232: 함수 속성¶
Python 2.1에서 함수에는 임의의 정보가 첨부될 수 있게 되었습니다. 사람들은 보통 __doc__ 속성이 함수에 어떤 정보를 첨부할 수 있는 유일한 방법이었기 때문에, docstrings를 사용하여 함수 및 메서드에 대한 정보를 저장했습니다. 예를 들어, Zope 웹 애플리케이션 서버에서는 함수가 docstring을 가짐으로써 공개 액세스에 안전한 것으로 표시되며, John Aycock의 SPARK 파싱 프레임워크에서는 docstrings가 파싱할 BNF 문법의 일부를 담습니다. 이러한 과부하는 좋지 않은데, docstrings는 실제로 함수의 문서를 저장하기 위해 의도되었기 때문에, 예를 들어 Zope에서 비공개 사용 목적의 함수를 적절하게 문서화할 수 없음을 의미합니다.
이제 일반적인 Python 구문을 사용하여 함수에 임의의 속성을 설정하고 검색할 수 있습니다:
def f(): pass
f.publish = 1
f.secure = 1
f.grammar = "A ::= B (C D)*"
속성을 포함하는 딕셔너리는 함수가 가진 __dict__ 속성과 달리, 함수에서는 __dict__`에 새로운 딕셔너리를 실제로 할당할 수 있지만, 새로운 값은 일반적인 Python 딕셔너리에 제한되며, :class:!UserDict` 인스턴스나 매핑처럼 동작하는 다른 임의의 객체로 트릭을 쓸 수 없습니다.
더 보기
- PEP 232 - 함수 속성
Barry Warsaw가 작성하고 구현함.
PEP 235: 케이스에 무감한 플랫폼에서 모듈 임포트¶
일부 운영 체제는 파일 시스템이 대소문자를 구분하지 않습니다. MacOS와 Windows가 주된 예이며, 이러한 시스템에서는 FILE.PY``와 ``file.py 파일명을 구분하는 것이 불가능합니다. 비록 그들이 파일 이름을 원래 케이스로 저장할지라도 (역시 케이스 보존적입니다).
Python 2.1에서는 import 문이 대소문자를 구분하지 않는 플랫폼에서 대소문자 구분을 시뮬레이션하는 데 작동합니다. 이제 파이썬은 기본적으로 첫 번째 대소문자 구분 일치를 검색하며, 만약 그러한 파일을 찾을 수 없으면 ImportError`를 발생시키므로, ``import file``은 ``FILE.PY``라는 모듈을 가져오지 않습니다. 대소문자 구분하지 않는 매칭은 파이썬 인터프리터를 시작하기 전에 :envvar:`PYTHONCASEOK 환경 변수를 설정하여 요청할 수 있습니다.
PEP 217: 대화형 표시 후크¶
파이썬 인터프리터를 대화형으로 사용할 때, 명령어의 출력은 내장된 repr() 함수를 사용하여 표시됩니다. Python 2.1부터는 sys.displayhook() 변수를 콜러블 객체로 설정할 수 있으며, 이 객체가 repr() 대신 호출됩니다. 예를 들어, 이를 특별한 보기 좋게 인쇄하는 함수로 설정할 수 있습니다:
>>> # 재귀 데이터 구조 생성
... L = [1,2,3]
>>> L.append(L)
>>> L # 파이썬의 기본 출력 표시
[1, 2, 3, [...]]
>>> # 표시 함수로 pprint.pprint() 사용
... import sys, pprint
>>> sys.displayhook = pprint.pprint
>>> L
[1, 2, 3, <id=135143996의 리스트에 대한 재귀>]
>>>
더 보기
- PEP 217 - 대화형 사용을 위한 표시 후크
Moshe Zadka가 작성하고 구현했습니다.
PEP 208: 새로운 형 변환 모델¶
C 레벨에서 숫자의 강제 변환 방식이 크게 수정되었습니다. 이는 파이썬의 C 확장을 작성하는 개발자에게만 영향을 미치며, 숫자 연산을 지원하는 확장 타입을 작성할 때 더 많은 유연성을 허용합니다.
확장 타입은 이제 자신들의 PyTypeObject 구조 내에 타입 플래그 Py_TPFLAGS_CHECKTYPES 를 설정하여 새로운 강제 변환 모델을 지원함을 나타낼 수 있습니다. 그러한 확장 타입에서 숫자 슬롯 함수는 더 이상 모두 같은 타입의 두 인수가 전달될 것이라고 가정할 수 없습니다. 대신 서로 다른 타입의 두 인수가 전달될 수 있으며, 이때는 자체적인 내부 강제 변환을 수행할 수 있습니다. 슬롯 함수가 처리할 수 없는 타입을 전달받으면, Py_NotImplemented 단일 객체(singleton value)를 참조하여 실패를 나타낼 수 있습니다. 그러면 다른 타입의 숫자 함수가 시도되며, 어쩌면 그 함수가 연산을 처리할 수 있을 수도 있습니다. 만약 다른 타입도 Py_NotImplemented 를 반환한다면, TypeError 가 발생합니다. 파이썬으로 작성된 숫자 메서드는 또한 Py_NotImplemented 를 반환할 수 있으며, 이는 인터프리터가 메서드가 존재하지 않는 것처럼 행동하게 만듭니다 (예: TypeError 를 발생시키거나, 다른 객체의 숫자 메서드를 시도하는 경우).
더 보기
- PEP 208 - 강제 변환 모델 재정비
Neil Schemenauer가 작성하고 구현했으며, Marc-André Lemburg의 초기 작업에 크게 기반을 두고 있습니다. 이 문서를 읽어보시면 숫자 연산이 C 레벨에서 이제 어떻게 처리될지에 대한 미세한 부분을 이해하는 데 도움이 될 것입니다.
PEP 241: 파이썬 패키지의 메타데이터¶
파이썬 사용자들의 흔한 불만 중 하나는 존재하는 모든 파이썬 모듈의 단일 카탈로그가 없다는 것입니다. T. Middleton의 파르나소스의 저장고(www.vex.net/parnassus/) (2009년 2월 폐지, `인터넷 아카이브 Wayback Machine <https://web.archive.org/web/20090130140102/http://www.vex.net/parnassus/>`에서 이용 가능)가 가장 큰 파이썬 모듈 카탈로그였지만, 저장소에 소프트웨어를 등록하는 것은 선택 사항이었으며 많은 사람들이 신경 쓰지 않았습니다.
이 문제를 해결하기 위한 첫 번째 작은 단계로, Distutils sdist 명령어를 사용하여 패키징된 파이썬 소프트웨어는 패키지의 이름, 버전, 작성자(카탈로그 용어로는 메타데이터 등)와 같은 정보를 담고 있는 PKG-INFO`라는 파일을 포함하게 됩니다. :pep:`241`에는 :file:`PKG-INFO 파일에 포함될 수 있는 모든 필드의 전체 목록이 포함되어 있습니다. 사람들이 Python 2.1을 사용하여 소프트웨어를 패키징하기 시작하면서, 점점 더 많은 패키지가 메타데이터를 포함하게 되어 자동화된 카탈로그 시스템을 구축하고 실험하는 것이 가능해집니다. 이런 경험을 거치면서, 정말 좋은 카탈로그를 설계하고 이를 Python 2.2에 지원하는 것이 가능할지도 모릅니다. 예를 들어, Distutils sdist 및 bdist_* 명령어는 패키지를 카탈로그 서버에 자동으로 업로드하는 upload 옵션을 지원할 수 있습니다.
:file:`PKG-INFO`를 포함하는 패키지를 Python 2.1을 사용하지 않더라도 만들 수 있습니다. 그 이유는 이전 버전의 Python 사용자를 위해 Distutils의 새 릴리스가 제작될 것이기 때문입니다. Distutils 버전 1.0.2에는 :pep:`241`에 설명된 변경 사항과 다양한 버그 수정 및 개선 사항이 포함되어 있습니다. 이것은 https://www.python.org/community/sigs/current/distutils-sig/의 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: ...
:file:`pydoc`은 또한 Tk 기반의 대화형 도움말 브라우저를 포함하고 있습니다. :file:`pydoc`은 금방 중독성이 되므로, 사용해 보세요!
표준 라이브러리에 단위 테스트를 위한 두 개의 다른 모듈이 추가되었습니다. Tim Peters가 기여한
doctest모듈은 독스트링에 포함된 예제를 실행하고 그 결과를 예상 출력과 비교하여 테스트 프레임워크를 제공합니다. Steve Purcell가 기여한 PyUnit은 JUnit에서 영감을 받은 단위 테스트 프레임워크로, 이는 차례로 Kent Beck의 Smalltalk 테스트 프레임워크를 각색한 것입니다. PyUnit에 대한 더 많은 정보는 https://pyunit.sourceforge.net/을 참조하십시오.difflib모듈은 두 시퀀스를 비교하고 한 시퀀스를 다른 시퀀스로 변환하는 데 필요한 변경 사항을 계산하는예를 들어, 이 모듈은 Unix :program:`diff프로그램과 유사한 도구를 작성하는 데 사용될 수 있으며, 실제로 샘플 프로그램인 :file:`Tools/scripts/ndiff.py`가 그러한 스크립트를 작성하는 방법을 보여줍니다.:mod:`curses.panel`은 ncurses 및 SYSV curses의 일부인 패널 라이브러리를 위한 래퍼이며, Thomas Gellekum가 기여했습니다. 패널 라이브러리는 깊이(depth)라는 추가 기능을 가진 창을 제공합니다. 창은 깊이 순서에서 더 높거나 더 낮은 위치로 이동할 수 있으며, 패널 라이브러리는 패널이 겹치는 곳과 보이는 영역을 알아냅니다.
PyXML 패키지는 Python 2.0 이후 몇 번의 릴리스를 거쳤으며, Python 2.1에는
xml패키지의 업데이트된 버전이 포함되어 있습니다. 주목할 만한 변경 사항으로는 Expat 1.2 이상 버전에 대한 지원, Expat 파서가 Python에서 지원되는 모든 인코딩의 파일을 처리할 수 있는 기능, 그리고 SAX, DOM 및minidom모듈에 대한 다양한 버그 수정 등이 있습니다.Ping은 또한 예외 처리용 다른 훅을 기여했습니다.
sys.excepthook`은 콜러블 객체로 설정될 수 있습니다. 예외가 어떤 :keyword:`try()…except블록에 의해 포착되지 않으면, 해당 예외는 :func:`sys.excepthook`으로 전달되며, 이곳에서 원하는 모든 작업을 수행할 수 있습니다. 제9회 파이썬 컨퍼런스에서 Ping은 이 훅에 대한 애플리케이션을 시연했습니다. 이 애플리케이션은 스택 프레임을 나열할 뿐만 아니라 각 프레임의 함수 인자와 지역 변수도 나열하는 확장된 트레이스백을 출력합니다.time모듈의 여러 함수, 예를 들어asctime()및time()))`()대신에 `time.asctime()`을 사용할 수 있습니다.이 변경 사항은 Thomas Wouters가 제안하고 구현했습니다.
ftplib모듈은 이제 패시브 모드에서 파일을 검색하는 것이 기본값이 되었습니다. 패시브 모드가 방화벽 뒤에서 작동할 가능성이 더 높기 때문입니다. 이 요청은 다른 Debian 패키지들이ftplib를 사용하여 파일을 검색하고 방화벽 뒤에서 작동하지 않는 문제가 발생했기 때문에 Debian 버그 추적 시스템에서 제기되었습니다. Netscape가 기본적으로 패시브 모드를 사용하고 사람들이 불평하는 경우가 적어 문제의 소지가 낮다고 판단되지만, 패시브 모드가 애플리케이션 또는 네트워크 설정에 적합하지 않은 경우, FTP 객체에서set_pasv(0)를 호출하여 패시브 모드를 비활성화하십시오.socket모듈에 원시 소켓 액세스에 대한 지원이 추가되었으며, Grant Edwards가 기여했습니다.pstats모듈은 이제 스크립트로 모듈이 실행될 때 파이썬 프로그램을 위한 타이밍 프로파일을 표시하는 간단한 대화형 통계 브라우저를 포함합니다. 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 라이브러리의 :c:func:`!getc`가 얼마나 느렸는지에 따라 플랫폼마다 다를 것이지만, 약 66%이며 일부 특정 운영 체제에서는 잠재적으로 훨씬 빠릅니다. Tim Peters는 comp.lang.python의 토론에 영감을 받아 이 변경에 대한 대부분의 벤치마킹과 코딩을 수행했습니다.파일 객체를 위한 새로운 모듈과 메서드가 Jeff Epler가 기여하여 추가되었습니다. 이 새로운 메서드인
xreadlines`는 기존의 :func:()!xrange` 내장 함수와 유사합니다.xreadlines`는 반복하기만 지원하는 불투명한 시퀀스 객체를 반환하며, 반복마다 줄을 읽지만 기존의 :meth:()!readlines` 메서드처럼 전체 파일을 메모리에 읽지는 않습니다. 사용 예시는 다음과 같습니다:for line in sys.stdin.xreadlines(): # ... 각 라인에 대해 무언가 수행... ...
라인 I/O 변경 사항에 대한 자세한 논의는 2001년 1월 1일 ~ 1월 15일의 python-dev 요약을 [https://mail.python.org/pipermail/python-dev/2001-January/](https://mail.python.org/pipermail/python-dev/2001-January/)에서 확인하세요.
딕셔너리를 순회하면서 내용을 파괴적으로 이터레이션 할 수 있도록 딕셔너리에 새로운 메서드,
popitem()``은 딕셔너리 ``D``에서 무작위 ``(키, 값)`()쌍을 제거하고 2개 튜플로 반환합니다. 이 기능은 Moshe Zadka의 제안과 예비 패치를 거쳐 주로 Tim Peters와 Guido van Rossum에 의해 구현되었습니다.모듈은 이제
from module import *가 사용될 때 어떤 이름이 임포트될지 제어할 수 있습니다. 이를 위해__all__속성을 정의하여 임포트할 이름 목록을 포함하면 됩니다. 흔한 불만 사항 중 하나는 해당 모듈이sys나string같은 다른 모듈을 임포트하는 경우,from module import *가 이를 임포팅 모듈의 네임스페이스에 추가한다는 것입니다. 이를 수정하려면, 단순히__all__에 공개된 이름들을 나열하기만 하면 됩니다:# 공개 이름을 나열합니다 __all__ = ['Database', 'open']
이 패치의 더 엄격한 버전은 Ben Wolfson에 의해 처음 제안되고 구현되었지만, python-dev 토론 이후 더 약한 최종 버전이 적용되었습니다.
이전에 비인쇄 가능한 문자에 대해 8진수 이스케이프를 사용하던 문자열에
repr`를 적용했습니다. 예를 들어, 줄 바꿈은 `()’012’였습니다. 이것은 파이썬의 C 계통의 잔재였지만, 오늘날 8진수는 실제적인 용도가 거의 없습니다. Ka-Ping Yee는 8진수 대신 16진수 이스케이프 사용을 제안하고, 적절한 문자에 대해서는 ``\n,\t,\r이스케이프를 사용하고 이 새로운 포맷팅을 구현했습니다.컴파일 시 감지되는 구문 오류는 이제 오류의 파일 이름과 라인 번호를 포함하는 예외를 발생시킬 수 있습니다. 이는 Jeremy Hylton이 수행한 컴파일러 재구축의 유쾌한 부수 효과입니다.
다른 모듈을 임포트하는 C 확장 기능은 이제 :c:func:`PyImport_ImportModule`를 사용하도록 변경되었으며, 이는 설치된 모든 임포트 훅을 사용한다는 의미입니다. 이 또한 C 코드로 다른 모듈을 임포트해야 하는 서드파티 확장 기능에도 권장됩니다.
유니코드 문자 데이터베이스의 크기가 Fredrik Lundh 덕분에 추가로 340K 줄어들었습니다.
다음 새로운 포트들이 기여되었습니다: MacOS X (Steven Majewski), Cygwin (Jason Tishler); RISCOS (Dietmar Schwertberger); Unixware 7 (Billy G. Allie).
그리고 일반적인 사소한 버그 수정, 사소한 메모리 누수, docstring 수정 및 기타 트윅 목록도 있지만, 나열할 가치가 없을 정도로 길습니다. 전체 자세한 내용은 CVS 로그를 확인하세요.
감사합니다¶
필자는 이 문서의 다양한 초안에 대해 제안을 해준 다음 분들에게 감사를 표하고 싶습니다: Graeme Cross, David Goodger, Jay Graves, Michael Hudson, Marc-André Lemburg, Fredrik Lundh, Neil Schemenauer, Thomas Wouters.