Python

Python 3.2의 새로운 기능

저자:

Raymond Hettinger

이 기사에서는 3.1과 비교하여 Python 3.2의 새로운 기능에 대해 설명합니다. Python 3.2는 2011년 2월 20일에 출시되었습니다. 몇 가지 주요 특징과 예시를 중점적으로 다룹니다. 자세한 내용은 Misc/NEWS 파일을 참조하십시오.

더 보기

PEP 392 - Python 3.2 출시 일정

PEP 384: 안정적인 ABI 정의

과거에는 특정 Python 버전용으로 빌드된 확장 모듈을 다른 Python 버전에서 사용할 수 없는 경우가 많았습니다. 특히 Windows에서는 Python의 모든 기능 릴리스 때마다 사용하려는 모든 확장 모듈을 다시 빌드해야 했습니다. 이러한 요구 사항은 확장 모듈이 Python 인터프리터 내부 구조에 자유롭게 접근할 수 있었기 때문에 발생한 결과였습니다.

Python 3.2부터 대안적인 접근 방식이 가능해졌습니다. 제한된 API(Py_LIMITED_API 정의)를 사용하는 확장 모듈은 많은 내부 구조를 사용할 수 없지만, 여러 릴리스 동안 안정성이 보장되는 일련의 API 함수들로 제한됩니다. 그 결과, 이 모드로 빌드된 3.2용 확장 모듈은 3.3, 3.4 등에서도 작동합니다. 메모리 구조의 세부 정보를 활용하는 확장 모듈도 여전히 빌드할 수 있지만, 매 기능 릴리스마다 재컴파일이 필요합니다.

더 보기

PEP 384 - 안정적인 ABI 정의

Martin von Löwis가 작성한 PEP.

PEP 389: argparse 명령행 파싱 모듈

위치 인자(단순 옵션뿐만 아니라), 서브 명령, 필수 옵션 및 기타 일반적인 옵션 지정 및 검증 패턴을 지원하지 못하는 optparse 의 한계를 극복하기 위해 새로운 명령행 파싱 모듈인 argparse 가 도입되었습니다.

이 모듈은 이미 서드파티 모듈로서 커뮤니티에서 널리 성공을 거두었습니다. 이전 버전보다 기능이 더 풍부한 argparse 모듈은 이제 명령행 처리를 위한 기본 모듈로 사용됩니다. 이전 모듈은 여전히 그것에 의존하는 상당량의 레거시 코드 때문에 계속 제공됩니다.

결과를 특정 선택 사항으로 제한하고, 도움말 화면에 metavar 를 지정하며, 하나 이상의 위치 인자가 있는지 확인하고, 필수 옵션을 설정하는 등의 기능을 보여주는 주석이 달린 예제 파서입니다:

import argparse
parser = argparse.ArgumentParser(
            description = 'Manage servers',         # 도움말용 기본 설명
            epilog = 'Tested on Solaris and Linux') # 도움말 뒤에 표시됨
parser.add_argument('action',                       # 인자 이름
            choices = ['deploy', 'start', 'stop'],  # 허용되는 세 가지 값
            help = 'action on each target')         # 도움말 메시지
parser.add_argument('targets',
            metavar = 'HOSTNAME',                   # 도움말 메시지에서 사용되는 변수 이름
            nargs = '+',                            # 하나 이상의 대상을 요구함
            help = 'url for target machines')       # 도움말 메시지 설명
parser.add_argument('-u', '--user',                 # -u 또는 --user 옵션
            required = True,                        # 필수 인자로 설정
            help = 'login as user')

명령 문자열에 파서를 적용하는 예시:

>>> cmd = 'deploy sneezy.example.com sleepy.example.com -u skycaptain'
>>> result = parser.parse_args(cmd.split())
>>> result.action
'deploy'
>>> result.targets
['sneezy.example.com', 'sleepy.example.com']
>>> result.user
'skycaptain'

파서가 자동으로 생성한 도움말의 예시:

>>> parser.parse_args('-h'.split())

usage: manage_cloud.py [-h] -u USER
                       {deploy,start,stop} HOSTNAME [HOSTNAME ...]

Manage servers

positional arguments:
  {deploy,start,stop}   action on each target
  HOSTNAME              url for target machines

optional arguments:
  -h, --help            show this help message and exit
  -u USER, --user USER  login as user

Tested on Solaris and Linux

argparse 의 특히 유용한 기능은 각각 고유한 인자 패턴과 도움말 표시를 가진 서브파서를 정의할 수 있는 능력입니다:

import argparse
parser = argparse.ArgumentParser(prog='HELM')
subparsers = parser.add_subparsers()

parser_l = subparsers.add_parser('launch', help='Launch Control')   # 첫 번째 서브그룹
parser_l.add_argument('-m', '--missiles', action='store_true')
parser_l.add_argument('-t', '--torpedos', action='store_true')

parser_m = subparsers.add_parser('move', help='Move Vessel',        # 두 번째 서브그룹
                                     aliases=('steer', 'turn'))         # 동등한 이름
parser_m.add_argument('-c', '--course', type=int, required=True)
parser_m.add_argument('-s', '--speed', type=int, default=0)
$ ./helm.py --help                         # 최상위 도움말 (launch 및 move)
$ ./helm.py launch --help                  # launch 옵션에 대한 도움말
$ ./helm.py launch --missiles              # missiles=True 및 torpedos=False로 설정
$ ./helm.py steer --course 180 --speed 5   # 이동 파라미터 설정

더 보기

PEP 389 - 새로운 명령줄 파싱 모듈

Steven Bethard가 작성한 PEP입니다.

optparse 와의 차이점에 대한 자세한 내용은 optparse 코드를 argparse 로 마이그레이션 를 참조하십시오.

PEP 391: 로깅을 위한 딕셔너리 기반 구성

logging 모듈은 두 가지 종류의 구성을 제공했는데, 하나는 각 옵션에 대한 함수 호출을 사용하는 방식이고 다른 하나는 configparser 형식으로 저장된 외부 파일에 의해 구동되는 방식입니다. 이러한 옵션들은 JSON 또는 YAML 파일로부터 구성을 생성하는 유연성을 제공하지 못했으며, 명령줄에서 로거 옵션을 지정할 때 필요한 점진적 구성(incremental configuration)도 지원하지 않았습니다.

더 유연한 방식을 지원하기 위해, 이제 이 모듈은 일반 파이썬 딕셔너리로 로깅 구성을 지정하는 logging.config.dictConfig() 를 제공합니다. 구성 옵션에는 포매터(formatter), 핸들러(handler), 필터(filter), 그리고 로거(logger)가 포함됩니다. 다음은 작동 가능한 구성 딕셔너리 예제입니다:

{"version": 1,
 "formatters": {"brief": {"format": "%(levelname)-8s: %(name)-15s: %(message)s"},
                "full": {"format": "%(asctime)s %(name)-15s %(levelname)-8s %(message)s"}
                },
 "handlers": {"console": {
                   "class": "logging.StreamHandler",
                   "formatter": "brief",
                   "level": "INFO",
                   "stream": "ext://sys.stdout"},
              "console_priority": {
                   "class": "logging.StreamHandler",
                   "formatter": "full",
                   "level": "ERROR",
                   "stream": "ext://sys.stderr"}
              },
 "root": {"level": "DEBUG", "handlers": ["console", "console_priority"]}}

해당 딕셔너리가 conf.json 이라는 파일에 저장되어 있다면, 다음과 같은 코드로 로드하고 호출할 수 있습니다:

>>> import json, logging.config
>>> with open('conf.json') as f:
...     conf = json.load(f)
...
>>> logging.config.dictConfig(conf)
>>> logging.info("Transaction completed normally")
INFO    : root           : Transaction completed normally
>>> logging.critical("Abnormal termination")
2011-02-17 11:14:36,694 root            CRITICAL Abnormal termination

더 보기

PEP 391 - 로깅을 위한 딕셔너리 기반 구성

Vinay Sajip이 작성한 PEP입니다.

PEP 3148: concurrent.futures 모듈

동시성을 생성하고 관리하는 코드가 새로운 최상위 네임스페이스인 concurrent*에 모이고 있습니다. 이의 첫 번째 구성 요소는 스레드와 프로세스를 관리하기 위한 일관된 고수준 인터페이스를 제공하는 *futures 패키지입니다.

concurrent.futures 의 설계는 java.util.concurrent 패키지에서 영감을 받았습니다. 해당 모델에서 실행 중인 호출과 그 결과는 스레드, 프로세스 및 원격 프로시저 호출(RPC)에서 공통적인 기능을 추상화한 Future 객체로 표현됩니다. 이 객체는 상태 확인(실행 중 또는 완료), 타임아웃, 취소, 콜백 추가, 결과 또는 예외에 대한 접근을 지원합니다.

새 모듈의 주요 기능은 호출을 실행하고 관리하기 위한 한 쌍의 익스큐터(executor) 클래스입니다. 익스큐터의 목표는 병렬 호출을 수행하기 위해 기존 도구들을 더 쉽게 사용하는 것입니다. 이들은 리소스 풀 설정, 호출 실행, 결과 큐 생성, 타임아웃 처리 추가, 그리고 전체 스레드, 프로세스 또는 원격 프로시저 호출 수 제한에 필요한 노력을 줄여줍니다.

이상적으로, 각 애플리케이션은 프로세스 및 스레드 제한을 중앙에서 관리할 수 있도록 여러 컴포넌트에서 단일 익스큐터를 공유해야 합니다. 이는 각 컴포넌트가 리소스 관리를 위해 서로 경쟁하는 전략을 가질 때 발생하는 설계상의 문제를 해결해 줍니다.

두 클래스는 세 가지 메서드를 가진 공통 인터페이스를 공유합니다: 콜러블을 예약하고 Future 객체를 반환하는 submit(), 여러 비동기 호출을 동시에 예약하는 map(), 그리고 리소스를 해제하는 shutdown(). 이 클래스는 context manager 이므로, 현재 대기 중인 퓨처(future)의 실행이 완료될 때 리소스가 자동으로 해제되도록 보장하는 with 문에서 사용할 수 있습니다.

ThreadPoolExecutor 의 간단한 예제는 파일을 복사하기 위해 4개의 병렬 스레드를 실행하는 것입니다:

import concurrent.futures, shutil
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as e:
    e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
    e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
    e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
    e.submit(shutil.copy, 'src3.txt', 'dest4.txt')

더 보기

PEP 3148 - 퓨처(Futures) – 계산을 비동기적으로 실행

Brian Quinlan이 작성한 PEP입니다.

Threaded Parallel URL reads를 위한 코드, 스레드를 사용하여 여러 웹 페이지를 병렬로 가져오는 예제입니다.

병렬 소수 계산을 위한 코드, ProcessPoolExecutor 를 시연하는 예제입니다.

PEP 3147: PYC 저장소 디렉터리

.pyc 파일에 바이트 코드를 캐싱하는 파이썬의 방식은 여러 파이썬 인터프리터가 존재하는 환경에서 제대로 작동하지 않았습니다. 만약 하나의 인터프리터가 다른 인터프리터에 의해 생성된 캐시 파일을 발견하면, 소스를 다시 컴파일하고 캐시 파일을 덮어써서 캐싱의 이점을 잃게 됩니다.

리눅스 배포판이 여러 버전의 파이썬을 함께 제공하는 것이 일반화되면서 “pyc fights” 문제가 더욱 두드러지게 되었습니다. 이러한 충돌은 Unladen Swallow와 같은 CPython 대안 환경에서도 발생합니다.

이 문제를 해결하기 위해 파이썬의 임포트 메커니즘이 각 인터프리터에 대해 고유한 파일 이름을 사용하도록 확장되었습니다. 이제 Python 3.2, Python 3.3, Unladen Swallow가 각각 “mymodule.pyc”라는 파일을 두고 경쟁하는 대신, “mymodule.cpython-32.pyc”, “mymodule.cpython-33.pyc”, “mymodule.unladen10.pyc”를 찾게 됩니다. 또한 이러한 새로운 파일들이 소스 디렉터리를 어지럽히는 것을 방지하기 위해, pyc 파일은 이제 패키지 디렉터리 아래의 “__pycache__” 디렉터리에 모아집니다.

파일 이름과 대상 디렉터리 외에도, 새로운 방식에는 프로그래머가 확인할 수 있는 몇 가지 측면이 있습니다:

  • 임포트된 모듈은 이제 실제로 임포트된 파일의 이름을 저장하는 __cached__ 속성을 가집니다.

    >>> import collections
    >>> collections.__cached__
    'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
    
  • 각 인터프리터에 고유한 태그는 imp 모듈에서 접근할 수 있습니다.

    >>> import imp
    >>> imp.get_tag()
    'cpython-32'
    
  • 임포트된 파일로부터 소스 파일 이름을 추론하는 스크립트는 이제 더 똑똑해져야 합니다. 단순히 “.pyc” 파일명에서 “c”를 제거하는 것만으로는 충분하지 않습니다. 대신, imp 모듈의 새 함수들을 사용하십시오:

    >>> imp.source_from_cache('c:/py32/lib/__pycache__/collections.cpython-32.pyc')
    'c:/py32/lib/collections.py'
    >>> imp.cache_from_source('c:/py32/lib/collections.py')
    'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
    
  • The py_compile and compileall modules have been updated to reflect the new naming convention and target directory. The command-line invocation of compileall has new options: -i for specifying a list of files and directories to compile and -b which causes bytecode files to be written to their legacy location rather than __pycache__.

  • importlib.abc 모듈이 바이트 코드 파일을 로드하기 위한 새로운 추상 기본 클래스 와 함께 업데이트되었습니다. 오래된 ABC인 PyLoaderPyPycLoader 는 폐지되었습니다(Python 3.1과의 호환성을 유지하는 방법에 대한 지침은 문서에 포함되어 있습니다).

더 보기

PEP 3147 - PYC 저장소 디렉터리

Barry Warsaw가 작성한 PEP입니다.

PEP 3149: ABI 버전 태그가 붙은 .so 파일

PYC 저장소 디렉터리는 여러 바이트 코드 캐시 파일이 공존할 수 있게 합니다. 이 PEP는 공유 객체 파일에 대해 공통 디렉터리를 제공하고 버전마다 고유한 이름을 부여함으로써 유사한 메커니즘을 구현합니다.

공통 디렉터리는 “pyshared”이며 파일 이름은 파이썬 구현체(CPython, PyPy, Jython 등), 메이저 및 마이너 버전 번호, 선택적 빌드 플래그(디버그용 “d”, pymalloc용 “m”, 와이드 유니코드용 “u”)를 식별하여 구분됩니다. 임의의 패키지 “foo”에 대해 배포 패키지를 설치할 때 다음과 같은 파일들을 볼 수 있습니다:

/usr/share/pyshared/foo.cpython-32m.so
/usr/share/pyshared/foo.cpython-33md.so

파이썬 자체에서는 sysconfig 모듈의 함수를 통해 태그에 접근할 수 있습니다:

>>> import sysconfig
>>> sysconfig.get_config_var('SOABI')       # 버전 태그 찾기
'cpython-32mu'
>>> sysconfig.get_config_var('EXT_SUFFIX')  # 전체 파일 확장자 찾기
'.cpython-32mu.so'

더 보기

PEP 3149 - ABI 버전 태그가 붙은 .so 파일

Barry Warsaw가 작성한 PEP입니다.

PEP 3333: Python 웹 서버 게이트웨이 인터페이스(WSGI) v1.0.1

이 정보성 PEP는 WSGI 프로토콜에서 바이트(byte)/텍스트 문제를 처리하는 방법을 명확히 합니다. 문제는 HTTP 프로토콜 자체가 바이트 중심임에도 불구하고, Python 3에서는 문자열 처리를 str 타입으로 처리하는 것이 가장 편리하기 때문입니다.

이 PEP는 요청/응답 헤더 및 메타데이터에 사용되는 소위 네이티브 문자열(native strings) 과 요청 및 응답의 본체(body)에 사용되는 바이트 문자열(byte strings) 을 구분합니다.

네이티브 문자열 은 항상 str 타입이지만, Latin-1 인코딩을 사용하여 바이트로 변환 가능한 U+0000 에서 U+00FF 사이의 코드 포인트로 제한됩니다. 이 문자열들은 환경 딕셔너리의 키와 값, 그리고 start_response() 함수에서의 응답 헤더 및 상태에 사용됩니다. 이들은 인코딩과 관련하여 RFC 2616 을 따라야 합니다. 즉, ISO-8859-1 문자여야 하거나 RFC 2047 MIME 인코딩을 사용해야 합니다.

Python 2에서 WSGI 애플리케이션을 이식하는 개발자를 위한 주요 사항은 다음과 같습니다.

  • 만약 애플리케이션이 이미 Python 2에서 헤더에 문자열을 사용했다면, 변경이 필요 없습니다.

  • 대신 애플리케이션이 출력 헤더를 인코딩하거나 입력 헤더를 디코딩했다면, 해당 헤더를 Latin-1으로 다시 인코딩해야 합니다. 예를 들어, utf-8로 인코딩된 출력 헤더가 h.encode('utf-8') 을 사용했다면 이제는 h.encode('utf-8').decode('latin-1') 를 사용하여 바이트에서 네이티브 문자열로 변환해야 합니다.

  • 애플리케이션에 의해 생성되거나 write() 메서드를 통해 전송되는 값은 반드시 바이트 문자열이어야 합니다. start_response() 함수와 environ은 네이티브 문자열을 사용해야 합니다. 이 둘을 혼합해서 사용할 수 없습니다.

CGI-to-WSGI 경로 또는 기타 CGI 스타일 프로토콜을 작성하는 서버 구현자의 경우, 기반 플랫폼이 다른 관례를 따르더라도 사용자가 네이티브 문자열을 사용하여 환경에 접근할 수 있어야 합니다. 이 간극을 메우기 위해 wsgiref 모듈에 wsgiref.handlers.read_environ() 이라는 새로운 함수가 추가되었으며, 이는 os.environ 의 CGI 변수를 네이티브 문자열로 트랜스코딩하고 새 딕셔너리를 반환합니다.

더 보기

PEP 3333 - Python Web Server Gateway Interface v1.0.1

Phillip Eby가 작성한 PEP.

이외의 언어 변경 사항

핵심 파이썬 언어에 가해진 일부 작은 변경 사항은 다음과 같습니다:

  • format()str.format() 을 위한 문자열 포맷팅에서 # 포맷 문자에 대한 새로운 기능이 추가되었습니다. 이전에는 이진수, 팔진수 또는 16진수의 정수에 대해 각각 ‘0b’, ‘0o’, ‘0x’로 출력이 시작되었습니다. 이제는 실수(float), 복소수(complex) 및 Decimal도 처리할 수 있으며, 뒤에 숫자가 없더라도 출력에 항상 소수점이 포함됩니다.

    >>> format(20, '#o')
    '0o24'
    >>> format(12.34, '#5.0f')
    '  12.'
    

    (Mark Dickinson이 제안하고 Eric Smith가 bpo-7094 에서 구현했습니다.)

  • 임의의 mapping 객체를 수용함으로써 기존 str.format() 메서드의 기능을 확장하는 새로운 str.format_map() 메서드가 추가되었습니다. 이 새 메서드를 사용하면 defaultdict, Shelf, ConfigParser 또는 dbm 과 같은 파이썬의 다양한 딕셔너리 유사 객체와 문자열 포맷팅을 사용하는 것이 가능해집니다. 또한 검색 전에 키를 정규화하거나 알 수 없는 키에 대해 __missing__() 메서드를 제공하는 사용자 정의 dict 하위 클래스에도 유용합니다.

    >>> import shelve
    >>> d = shelve.open('tmp.shl')
    >>> 'The {project_name} status is {status} as of {date}'.format_map(d)
    'The testing project status is green as of February 15, 2011'
    
    >>> class LowerCasedDict(dict):
    ...     def __getitem__(self, key):
    ...         return dict.__getitem__(self, key.lower())
    ...
    >>> lcd = LowerCasedDict(part='widgets', quantity=10)
    >>> 'There are {QUANTITY} {Part} in stock'.format_map(lcd)
    'There are 10 widgets in stock'
    
    >>> class PlaceholderDict(dict):
    ...     def __missing__(self, key):
    ...         return '<{}>'.format(key)
    ...
    >>> 'Hello {name}, welcome to {location}'.format_map(PlaceholderDict())
    'Hello <name>, welcome to <location>'
    

(Raymond Hettinger가 제안하고 Eric Smith가 bpo-6081 에서 구현했습니다.)

  • 이제 인터프리터를 시작할 때 –q 옵션을 사용하여 대화형 모드에서 저작권 및 버전 정보가 표시되지 않도록 방지할 수 있습니다. 이 옵션은 sys.flags 속성을 통해 확인할 수 있습니다.

    $ python -q
    >>> sys.flags
    sys.flags(debug=0, division_warning=0, inspect=0, interactive=0,
    optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0,
    ignore_environment=0, verbose=0, bytes_warning=0, quiet=1)
    

    (Marcin Wojdyr가 bpo-1772833 에서 기여했습니다.)

  • The hasattr() function works by calling getattr() and detecting whether an exception is raised. This technique allows it to detect methods created dynamically by __getattr__() or __getattribute__() which would otherwise be absent from the class dictionary. Formerly, hasattr would catch any exception, possibly masking genuine errors. Now, hasattr has been tightened to only catch AttributeError and let other exceptions pass through:

    >>> class A:
    ...     @property
    ...     def f(self):
    ...         return 1 // 0
    ...
    >>> a = A()
    >>> hasattr(a, 'f')
    Traceback (most recent call last):
      ...
    ZeroDivisionError: integer division or modulo by zero
    

    (Yury Selivanov이 발견하고 Benjamin Peterson이 bpo-9666 에서 수정했습니다.)

  • 실수 또는 복소수의 str() 은 이제 해당 값의 repr() 과 동일합니다. 이전에는 str() 형태가 더 짧았으나 이는 혼란을 야기했으며, 현재는 가장 짧은 가능성 있는 repr() 이 기본으로 표시되므로 더 이상 필요하지 않습니다.

    >>> import math
    >>> repr(math.pi)
    '3.141592653589793'
    >>> str(math.pi)
    '3.141592653589793'
    

    (Mark Dickinson이 제안하고 bpo-9337 에서 구현했습니다.)

  • memoryview 객체에 이제 release() 메서드가 추가되었으며 컨텍스트 관리 프로토콜도 지원합니다. 이를 통해 원본 객체로부터 버퍼를 요청할 때 할당된 리소스를 제때 해제할 수 있습니다.

    >>> with memoryview(b'abcdefgh') as v:
    ...     print(v.tolist())
    [97, 98, 99, 100, 101, 102, 103, 104]
    

    (Antoine Pitrou가 bpo-9757 에서 추가했습니다.)

  • 이전에는 중첩된 블록 내에서 자유 변수로 나타나는 이름을 로컬 네임스페이스에서 삭제하는 것이 허용되지 않았습니다.

    def outer(x):
        def inner():
            return x
        inner()
        del x
    

    이제 이것이 허용됩니다. except 절의 대상은 초기화된다는 점을 기억하십시오. 따라서 Python 2.6에서는 작동했지만 Python 3.1에서 SyntaxError 를 발생시켰던 이 코드가 이제 다시 작동합니다.

    def f():
        def print_error():
            print(e)
        try:
            something
        except Exception as e:
            print_error()
            # 여기서 암시적인 "del e" 발생
    

    (bpo-4617 을 참조하십시오.)

  • Struct sequence types 는 이제 tuple의 하위 클래스입니다. 이는 os.stat(), time.gmtime(), 그리고 sys.version_info 가 반환하는 C 구조체가 이제 named tuple 처럼 작동하며, 인자로 튜플을 기대하는 함수나 메서드와 호환됨을 의미합니다. 이는 C 구조체를 순수 파이썬 대응물만큼 유연하게 만드는 데 큰 진전을 의미합니다.

    >>> import sys
    >>> isinstance(sys.version_info, tuple)
    True
    >>> 'Version %d.%d.%d %s(%d)' % sys.version_info
    'Version 3.2.0 final(0)'
    

    (Arfrever Frehtes Taifersar Arahesis가 제안하고 Benjamin Peterson이 bpo-8413 에서 구현했습니다.)

  • 경고(Warning)를 이제 커맨드라인에서 –W 를 사용하는 대신 PYTHONWARNINGS 환경 변수를 사용하여 더 쉽게 제어할 수 있습니다.

    $ export PYTHONWARNINGS='ignore::RuntimeWarning::,once::UnicodeWarning::'
    

    (Barry Warsaw가 제안하고 Philip Jenvey가 bpo-7301 에서 구현했습니다.)

  • 새로운 경고 카테고리인 ResourceWarning 이 추가되었습니다. 리소스 소비 또는 정리와 관련된 잠재적인 문제가 감지될 때 발생합니다. 일반 릴리스 빌드에서는 기본적으로 무시되지만, warnings 모듈이나 커맨드라인에서 제공하는 수단을 통해 활성화할 수 있습니다.

    gc.garbage 목록이 비어 있지 않고 gc.DEBUG_UNCOLLECTABLE 이 설정된 경우, 인터프리터 종료 시 ResourceWarning 이 발생하며 모든 수거 불가능한 객체가 출력됩니다. 이는 프로그래머에게 코드가 객체 최종화(finalization) 문제를 포함하고 있음을 알리기 위한 것입니다.

    명시적으로 닫히지 않은 file object 가 파괴될 때도 ResourceWarning 이 발생합니다. 이러한 객체의 해제자가 기본 운영 체제 리소스(대개 파일 디스크립터)를 닫도록 보장하지만, 객체 해용 지연은 특히 Windows 환경에서 다양한 문제를 일으킬 수 있습니다. 커맨드라인에서 경고를 활성화하는 예시는 다음과 같습니다.

    $ python -q -Wdefault
    >>> f = open("foo", "wb")
    >>> del f
    __main__:1: ResourceWarning: unclosed file <_io.BufferedWriter name='foo'>
    

    (Antoine Pitrou와 Georg Brandl이 bpo-10093bpo-477863 에서 추가했습니다.)

  • range objects now support index and count methods. This is part of an effort to make more objects fully implement the collections.Sequence abstract base class. As a result, the language will have a more uniform API. In addition, range objects now support slicing and negative indices, even with values larger than sys.maxsize. This makes range more interoperable with lists:

    >>> range(0, 100, 2).count(10)
    1
    >>> range(0, 100, 2).index(10)
    5
    >>> range(0, 100, 2)[5]
    10
    >>> range(0, 100, 2)[0:5]
    range(0, 10, 2)
    

    (Daniel Stutzbach이 bpo-9213, Alexander Belopolsky가 bpo-2690, Nick Coghlan이 bpo-10889 에서 기여했습니다.)

  • Py2.x의 내장 함수인 callable() 이 다시 도입되었습니다. 이는 isinstance(x, collections.Callable) 와 같은 표현식에서 abstract base class 를 사용하는 대신 간결하고 읽기 쉬운 대안을 제공합니다.

    >>> callable(max)
    True
    >>> callable(20)
    False
    

    (bpo-10518 을 참조하십시오.)

  • 파이썬의 가져오기(import) 메커니즘은 이제 경로 이름에 비-ASCII 문자가 포함된 디렉토리에 설치된 모듈도 로드할 수 있습니다. 이는 사용자 이름에 비-ASCII 문자가 포함된 사용자의 홈 디렉토리에서 발생하는 성가신 문제를 해결했습니다.

(Victor Stinner가 bpo-9425 에서 광범위한 작업을 수행했습니다.)

새로운, 개선된, 그리고 더 이상 사용되지 않는 모듈

파이썬 표준 라이브러리가 상당한 유지관리와 품질 개선을 거쳤습니다.

Python 3.2의 가장 큰 소식은 email 패키지, mailbox 모듈 및 nntplib 모듈이 이제 Python 3의 바이트/텍스트 모델과 올바르게 작동한다는 것입니다. 처음으로 혼합된 인코딩을 가진 메시지에 대한 올바른 처리가 가능해졌습니다.

표준 라이브러리 전반에 걸쳐 인코딩과 텍스트 대 바이트 문제에 더 세심한 주의를 기울였습니다. 특히, 운영 체제와의 상호작용에서 Windows MBCS 인코딩, 로케일 인식 인코딩 또는 UTF-8을 사용하여 비-ASCII 데이터를 더 잘 교환할 수 있게 되었습니다.

또 다른 중요한 성과는 SSL 연결 및 보안 인증서에 대한 대폭 강화된 지원이 추가된 것입니다.

또한, 더 많은 클래스가 with 문을 사용하여 편리하고 안정적인 리소스 정리를 지원하는 context manager 를 구현합니다.

email

Python 3에서 email 패키지의 사용성은 R. David Murray의 광범위한 노력으로 대부분 개선되었습니다. 문제는 전자 메일이 일반적으로 str 텍스트가 아닌 bytes 형태로 읽히고 저장되며, 단일 전자 메일 내에 여러 인코딩이 포함될 수 있다는 것이었습니다. 따라서 email 패키지는 바이트 형식으로 전자 메일 메시지를 구문 분석하고 생성할 수 있도록 확장되어야 했습니다.

  • 새로운 함수인 message_from_bytes()message_from_binary_file(), 그리고 새로운 클래스인 BytesFeedParserBytesParser 를 통해 바이너리 메시지 데이터를 모델 객체로 구문 분석할 수 있습니다.

  • 모델에 바이트 입력을 제공할 때, get_payload() 는 기본적으로 Content-Transfer-Encoding8bit 인 메시지 본문을 MIME 헤더에 명시된 문자 집합을 사용하여 디코딩하고 결과 문자열을 반환합니다.

  • 모델에 바이트 입력을 제공할 때, GeneratorContent-Transfer-Encoding8bit 인 메시지 본체를 7bit Content-Transfer-Encoding 으로 변환합니다.

    인코딩되지 않은 비 ASCII 바이트가 포함된 헤더는 unknown-8bit 문자 집합을 사용하여 RFC 2047 으로 인코딩된 것으로 간주됩니다.

  • 새로운 클래스인 BytesGenerator 은 출력으로 바이트를 생성하며, 모델 구축에 사용된 입력에 포함되어 있던 변경되지 않은 비 ASCII 데이터를 유지합니다. 여기에는 Content-Transfer-Encoding8bit 인 메시지 본신도 포함됩니다.

  • smtplibSMTP 클래스는 이제 sendmail() 메서드의 msg 인자로 바이트 문자열을 수용하며, 새로운 메서드인 send_message()Message 객체를 수용하고 옵션에 따라 객체에서 from_addrto_addrs 주소를 직접 가져올 수 있습니다.

(R. David Murray가 제안하고 구현함, bpo-4661bpo-10321.)

elementtree

xml.etree.ElementTree 패키지와 그 대응물인 xml.etree.cElementTree 가 버전 1.3으로 업데이트되었습니다.

여러 유용한 새 함수와 메서드가 추가되었습니다:

두 개의 메서드가 폐지되었습니다:

  • xml.etree.ElementTree.getchildren() 대신 list(elem) 을 사용하십시오.

  • xml.etree.ElementTree.getiterator() 대신 Element.iter 를 사용하십시오.

업데이트에 대한 자세한 내용은 Fredrik Lundh의 웹사이트에 있는 Introducing ElementTree 를 참조하십시오.

(Florent Xicluna와 Fredrik Lundh가 기여했습니다. bpo-6472.)

functools 모듈

  • functools 모듈에 함수 호출을 캐싱하기 위한 새로운 데코레이터가 포함됩니다. @functools.lru_cache 는 결과가 동일할 것으로 예상되는 경우 외부 리소스에 대한 반복적인 질의를 저장할 수 있습니다.

    예를 들어, 데이터베이스 조회 함수에 캐싱 데코레이터를 추가하면 인기 있는 검색에 대한 데이터베이스 액세스를 줄일 수 있습니다.

    >>> import functools
    >>> @functools.lru_cache(maxsize=300)
    ... def get_phone_number(name):
    ...     c = conn.cursor()
    ...     c.execute('SELECT phonenumber FROM phonelist WHERE name=?', (name,))
    ...     return c.fetchone()[0]
    
    >>> for name in user_requests:
    ...     get_phone_number(name)        # cached lookup
    

    효과적인 캐시 크기를 선택하는 데 도움을 주기 위해, 래핑된 함수는 캐시 통계를 추적하도록 인스트루먼트됩니다.

    >>> get_phone_number.cache_info()
    CacheInfo(hits=4805, misses=980, maxsize=300, currsize=300)
    

    phonelist 테이블이 업데이트되면 다음을 사용하여 오래된 캐시 내용을 삭제할 수 있습니다:

    >>> get_phone_number.cache_clear()
    

    (Raymond Hettinger가 기여하였으며 Jim Baker, Miki Tebeka, Nick Coghlan의 설계 아이디어를 반영했습니다. recipe 498245, recipe 577479, bpo-10586, bpo-10593 참조.)

  • @functools.wraps 데코레이터는 이제 원본 호출 가능 함수를 가리키는 __wrapped__ 속성을 추가합니다. 이를 통해 래핑된 함수를 조사할 수 있습니다. 또한 정의된 경우 __annotations__ 를 복사하며, 이제는 래핑된 callable에 정의되지 않았을 수 있는 __doc__ 와 같은 누락된 속성을 문제없이 건너뜁니다.

    위의 예제에서 원본 함수를 복원하여 캐시를 제거할 수 있습니다.

    >>> get_phone_number = get_phone_number.__wrapped__    # uncached function
    

    (Nick Coghlan 및 Terrence Cole에 의해 작성됨. bpo-9567, bpo-3445, bpo-8814.)

  • 풍부한 비교(rich comparison) 메서드를 가진 클래스를 작성하는 것을 돕기 위해, 새로운 데코레이터 @functools.total_ordering 이 기존의 등가 및 부등가 메서드를 사용하여 나머지 메서드들을 채워줍니다.

    예를 들어, __eq____lt__ 를 제공하면 @~functools.total_ordering__le__, __gt____ge__ 를 채우도록 할 수 있습니다:

    @total_ordering
    class Student:
        def __eq__(self, other):
            return ((self.lastname.lower(), self.firstname.lower()) ==
                    (other.lastname.lower(), other.firstname.lower()))
    
        def __lt__(self, other):
            return ((self.lastname.lower(), self.firstname.lower()) <
                    (other.lastname.lower(), other.firstname.lower()))
    

    total_ordering 데코레이터를 사용하면 나머지 비교 메서드가 자동으로 채워집니다.

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

  • To aid in porting programs from Python 2, the functools.cmp_to_key() function converts an old-style comparison function to modern key function:

    >>> # locale-aware sort order
    >>> sorted(iterable, key=cmp_to_key(locale.strcoll))
    

    정렬 예제 및 간단한 정렬 튜토리얼은 Sorting HowTo 튜토리얼을 참조하십시오.

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

itertools 모듈

  • itertools 모듈에 APL의 scan 연산자와 Numpy의 accumulate 함수를 모델로 한 새로운 accumulate() 기능이 추가되었습니다.

    >>> from itertools import accumulate
    >>> list(accumulate([8, 2, 50]))
    [8, 10, 60]
    
    >>> prob_dist = [0.1, 0.4, 0.2, 0.3]
    >>> list(accumulate(prob_dist))      # cumulative probability distribution
    [0.1, 0.5, 0.7, 1.0]
    

    accumulate() 를 사용한 예제는 random 모듈 예제 를 참조하십시오.

    (Raymond Hettinger가 기여하였으며 Mark Dickinson의 설계 제안이 반영되었습니다.)

컬렉션 모듈(collections)

  • collections.Counter 클래스는 이제 두 가지 형태의 인플레이스 뺄셈을 제공합니다. 기존의 -= 연산자는 포화 뺄셈 으로, 새로운 subtract() 메서드는 일반적인 뺄셈을 수행합니다. 전자는 양수 계수만 갖는 멀티셋 에 적합하며, 후자는 음수 계수를 허용하는 경우에 더 적합합니다.

    >>> from collections import Counter
    >>> tally = Counter(dogs=5, cats=3)
    >>> tally -= Counter(dogs=2, cats=8)    # saturating subtraction
    >>> tally
    Counter({'dogs': 3})
    
    >>> tally = Counter(dogs=5, cats=3)
    >>> tally.subtract(dogs=2, cats=8)      # regular subtraction
    >>> tally
    Counter({'dogs': 3, 'cats': -5})
    

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

  • The collections.OrderedDict class has a new method move_to_end() which takes an existing key and moves it to either the first or last position in the ordered sequence.

    기본값은 항목을 마지막 위치로 이동시키는 것입니다. 이는 od[k] = od.pop(k) 를 사용하여 항목을 갱신하는 것과 동일합니다.

    빠른 끝으로 이동 연산은 항목의 순서를 재배치하는 데 유용합니다. 예를 들어, 정렬된 딕셔너리를 사용하여 가장 오래된 항목부터 최근에 접근한 항목까지의 시퀀스를 추적할 수 있습니다.

    >>> from collections import OrderedDict
    >>> d = OrderedDict.fromkeys(['a', 'b', 'X', 'd', 'e'])
    >>> list(d)
    ['a', 'b', 'X', 'd', 'e']
    >>> d.move_to_end('X')
    >>> list(d)
    ['a', 'b', 'd', 'e', 'X']
    

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

  • collections.deque 클래스에 count()reverse() 라는 두 개의 새 메서드가 추가되어 list 객체를 대신하기 더 용이해졌습니다.

    >>> from collections import deque
    >>> d = deque('simsalabim')
    >>> d.count('s')
    2
    >>> d.reverse()
    >>> d
    deque(['m', 'i', 'b', 'a', 'l', 'a', 's', 'm', 'i', 's'])
    

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

스레딩

threading 모듈에 여러 스레드가 공통의 장벽 지점에 도달할 때까지 대기하게 하는 새로운 Barrier 동기화 클래스가 추가되었습니다. 장벽은 여러 전제 조건이 있는 작업이 모든 선행 작업이 완료될 때까지 실행되지 않도록 보장하는 데 유용합니다.

Barrier는 임의의 수의 스레드와 함께 작동할 수 있습니다. 이는 단 두 개의 스레드에 대해서만 정의되는 Rendezvous 를 일반화한 것입니다.

2단계 순환 장벽(cyclic barrier)으로 구현된 Barrier 객체는 루프에서 사용하기에 적합합니다. 별도의 fillingdraining 단계 덕분에 어떤 스레드도 루프를 돌아서 다시 장벽에 진입하기 전에 모든 스레드가 해제(drained)됨을 보장합니다. 장벽은 매 사이클마다 완전히 초기화됩니다.

barrier 사용 예시:

from threading import Barrier, Thread

def get_votes(site):
    ballots = conduct_election(site)
    all_polls_closed.wait()        # 모든 투표가 마감될 때까지 계산하지 않음
    totals = summarize(ballots)
    publish(site, totals)

all_polls_closed = Barrier(len(sites))
for site in sites:
    Thread(target=get_votes, args=(site,)).start()

이 예제에서 barrier는 모든 투표가 마감될 때까지 어떤 투표소에서도 투표를 집계할 수 없다는 규칙을 강제합니다. barrier를 사용한 해결 방법이 threading.Thread.join() 을 사용한 것과 유사하지만, 스레드가 barrier 지점을 통과한 후에도 살아있으며 계속해서 작업을 수행(투표 결과 요약)한다는 점에 주목하십시오.

선행 작업 중 어느 하나라도 멈추거나 지연될 수 있는 경우, 선택적 timeout 매개변수와 함께 장벽을 생성할 수 있습니다. 이 경우 모든 선행 작업이 장벽 지점에 도달하기 전에 타임아웃 기간이 지나면, 대기 중인 모든 스레드가 해제되고 BrokenBarrierError 예외가 발생합니다:

def get_votes(site):
    ballots = conduct_election(site)
    try:
        all_polls_closed.wait(timeout=midnight - time.now())
    except BrokenBarrierError:
        lockbox = seal_ballots(ballots)
        queue.put(lockbox)
    else:
        totals = summarize(ballots)
        publish(site, totals)

이 예제에서 장벽은 더 견고한 규칙을 강제합니다. 일부 투표소에서 자정 전에 작업을 마치지 못하면 장벽이 타임아웃되고, 투표용지는 봉인되어 나중에 처리하기 위해 큐에 저장됩니다.

병렬 컴퓨팅에서 장벽을 사용하는 방법에 대한 더 많은 예제는 Barrier Synchronization Patterns 를 참조하십시오. 또한, The Little Book of Semaphores3.6절 에 장벽에 대한 간단하면서도 상세한 설명이 포함되어 있습니다.

(Kristján Valur Jónsson가 기여하고 Jeffrey Yasskin이 bpo-8777 에서 API 리뷰를 수행함.)

datetime 및 time

  • datetime 모듈은 고정된 UTC 오프셋과 시간대 이름을 반환하여 tzinfo 인터페이스를 구현하는 새로운 타입인 timezone 을 포함합니다. 이를 통해 시간대를 인식하는 datetime 객체를 더 쉽게 생성할 수 있습니다:

    >>> import datetime as dt
    
    >>> dt.datetime.now(dt.timezone.utc)
    datetime.datetime(2010, 12, 8, 21, 4, 2, 923754, tzinfo=datetime.timezone.utc)
    
    >>> dt.datetime.strptime("01/01/2000 12:00 +0000", "%m/%d/%Y %H:%M %z")
    datetime.datetime(2000, 1, 1, 12, 0, tzinfo=datetime.timezone.utc)
    
  • 또한, timedelta 객체를 이제 float 으로 곱하거나 floatint 객체로 나눌 수 있습니다. 또한 timedelta 객체끼리 나누는 것도 가능합니다.

  • datetime.date.strftime() 메서드는 더 이상 1900년 이후의 연도로 제한되지 않습니다. 새로 지원되는 연도 범위는 1000년부터 9999년까지입니다.

  • 시간 튜플에 두 자릿수 연도가 사용될 때마다 해석은 time.accept2dyear`의 제어를 받습니다. 기본값은 ``True``이며, 이는 자릿수 연도의 경우 ``%y` strptime 형식을 다루는 POSIX 규칙에 따라 세기를 추측함을 의미합니다.

    Py3.2부터 세기 추측 휴리스틱을 사용하면 DeprecationWarning 이 발생합니다. 대신, 추측 없이 넓은 날짜 범위를 사용할 수 있도록 time.accept2dyearFalse 로 설정하는 것이 권장됩니다:

    >>> import time, warnings
    >>> warnings.resetwarnings()      # 기본 경고 필터 제거
    
    >>> time.accept2dyear = True      # 11이 11인지 2011인지 추측
    >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0))
    Warning (from warnings module):
      ...
    DeprecationWarning: Century info guessed for a 2-digit year.
    'Fri Jan  1 12:34:56 2011'
    
    >>> time.accept2dyear = False     # 허용되는 모든 범위의 날짜 사용
    >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0))
    'Fri Jan  1 12:34:56 11'
    

    여러 기능의 날짜 범위가 크게 확장되었습니다. time.accept2dyear 가 false일 때, time.asctime() 함수는 C int에 들어갈 수 있는 모든 연도를 허용하며, time.mktime()time.strftime() 함수는 해당 운영체제 기능에서 지원하는 전체 범위를 수용합니다.

(Alexander Belopolsky와 Victor Stinner가 bpo-1289118, bpo-5094, bpo-6641, bpo-2706, bpo-1777412, bpo-8013, bpo-10827 에서 기여함.)

math 모듈

math 모듈이 C99 표준에서 영감을 받은 6개의 새로운 함수와 함께 업데이트되었습니다.

isfinite() 함수는 특수 값을 감지하는 신뢰할 수 있고 빠른 방법을 제공합니다. 일반 숫자에 대해서는 True 를, Nan 또는 Infinity 에 대해서는 False 를 반환합니다.

>>> from math import isfinite
>>> [isfinite(x) for x in (123, 4.56, float('Nan'), float('Inf'))]
[True, True, False, False]

expm1() 함수는 거의 동일한 양을 빼는 과정에서 흔히 발생하는 정밀도 손실 없이 작은 x 값에 대해 e**x-1 을 계산합니다.

>>> from math import expm1
>>> expm1(0.013671875)   # more accurate way to compute e**x-1 for a small x
0.013765762467652909

erf() 함수는 확률 적분 또는 가우스 오차 함수 를 계산합니다. 보충 오차 함수인 erfc()1 - erf(x) 입니다.

>>> from math import erf, erfc, sqrt
>>> erf(1.0/sqrt(2.0))   # 1 표준편차 이내의 정규 분포 부분
0.682689492137086
>>> erfc(1.0/sqrt(2.0))  # 1 표준편차 밖의 정규 분포 부분
0.31731050786291404
>>> erf(1.0/sqrt(2.0)) + erfc(1.0/sqrt(2.0))
1.0

gamma() 함수는 팩토리얼 함수의 연속 확장입니다. 자세한 내용은 https://en.wikipedia.org/wiki/Gamma_function을 참조하십시오. 이 함수는 팩토리얼과 관련이 있기 때문에 x 가 작은 경우에도 값이 커질 수 있으므로, 감마 함수의 자연로그를 계산하는 lgamma() 함수도 제공됩니다.

>>> from math import gamma, lgamma
>>> gamma(7.0)           # six factorial
720.0
>>> lgamma(801.0)        # log(800 factorial)
4551.950730698041

(Mark Dickinson이 기여함.)

abc

abc 모듈이 이제 @~abc.abstractclassmethod@~abc.abstractstaticmethod 를 지원합니다.

이 도구들을 사용하면 특정 @classmethod 또는 @staticmethod 구현을 요구하는 추상 베이스 클래스 를 정의할 수 있습니다:

class Temperature(metaclass=abc.ABCMeta):
    @abc.abstractclassmethod
    def from_fahrenheit(cls, t):
        ...
    @abc.abstractclassmethod
    def from_celsius(cls, t):
        ...

(Daniel Urban이 패치를 제출함; bpo-5867.)

io 모듈

io.BytesIOmemoryview() 와 유사한 기능을 제공하는 새로운 메서드인 getbuffer() 가 추가되었습니다. 이 메서드는 복사본을 생성하지 않고 데이터를 편집할 수 있는 뷰를 생성합니다. 버퍼의 랜덤 액세스 및 슬라이스 표기법 지원은 인플레이스(in-place) 편집에 적합합니다:

>>> REC_LEN, LOC_START, LOC_LEN = 34, 7, 11

>>> def change_location(buffer, record_number, location):
...     start = record_number * REC_LEN + LOC_START
...     buffer[start: start+LOC_LEN] = location

>>> import io

>>> byte_stream = io.BytesIO(
...     b'G3805  storeroom  Main chassis    '
...     b'X7899  shipping   Reserve cog     '
...     b'L6988  receiving  Primary sprocket'
... )
>>> buffer = byte_stream.getbuffer()
>>> change_location(buffer, 1, b'warehouse  ')
>>> change_location(buffer, 0, b'showroom   ')
>>> print(byte_stream.getvalue())
b'G3805  showroom   Main chassis    '
b'X7899  warehouse  Reserve cog     '
b'L6988  receiving  Primary sprocket'

(Antoine Pitrou가 bpo-5506 에서 기여함.)

reprlib

커스텀 컨테이너를 위한 __repr__() 메서드를 작성할 때, 멤버가 컨테이너 자체를 참조하는 경우를 처리하는 것을 잊기 쉽습니다. Python의 내장 객체인 listset 은 재귀적인 표현 부분에 “…”을 표시하여 자기 참조를 처리합니다.

그러한 __repr__() 메서드 작성을 돕기 위해, reprlib 모듈에 __repr__() 으로의 재귀 호출을 감지하고 대신 자리 표시자 문자열로 대체하는 새로운 데코레이터인 @~reprlib.recursive_repr 가 추가되었습니다:

>>> class MyList(list):
...     @recursive_repr()
...     def __repr__(self):
...         return '<' + '|'.join(map(repr, self)) + '>'
...
>>> m = MyList('abc')
>>> m.append(m)
>>> m.append('x')
>>> print(m)
<'a'|'b'|'c'|...|'x'>

(Raymond Hettinger가 bpo-9826bpo-9840 에서 기여함.)

logging 모듈

위에 설명된 딕셔너리 기반 구성 외에도, logging 패키지에 많은 개선 사항이 포함되었습니다.

로깅 문서가 기본 튜토리얼 , 고급 튜토리얼 , 그리고 로깅 레시피 모음인 cookbook 으로 보강되었습니다. 이 문서들은 로깅을 배우는 가장 빠른 방법입니다.

logging.basicConfig() 설정 함수가 세 가지 다른 유형의 문자열 포매팅을 지원하기 위해 style 인수를 추가로 갖게 되었습니다. 기본값은 전통적인 % 형식을 위한 “%”이며, 새로운 str.format() 스타일을 위해 “{“로 설정하거나 string.Template 에서 제공하는 쉘 스타일 형식을 위해 “$”로 설정할 수 있습니다. 다음 세 가지 구성은 서로 동일합니다:

>>> from logging import basicConfig
>>> basicConfig(style='%', format="%(name)s -> %(levelname)s: %(message)s")
>>> basicConfig(style='{', format="{name} -> {levelname} {message}")
>>> basicConfig(style='$', format="$name -> $levelname: $message")

로깅 이벤트가 발생하기 전에 구성이 설정되지 않은 경우, 이제 WARNING 레벨 이상의 이벤트에 대해 sys.stderr 로 향하는 StreamHandler 를 사용하는 기본 구성이 제공됩니다. 이전에는 설정 전 발생하는 이벤트가 logging.raiseExceptions 값에 따라 예외를 발생시키거나 조용히 무시되었습니다. 새로운 기본 핸들러는 logging.lastResort 에 저장됩니다.

필터 사용이 단순화되었습니다. Filter 객체를 생성하는 대신, True 또는 False를 반환하는 모든 파이썬 호출 가능(callable) 개체가 조건문으로 사용될 수 있습니다.

유연성을 높이고 구성을 단순화하는 여러 다른 개선 사항이 있습니다. Python 3.2의 전체 변경 목록은 모듈 문서를 참조하십시오.

csv

csv 모듈이 새로운 방언인 unix_dialect 를 지원합니다. 이 방언은 모든 필드에 인용(quoting)을 적용하고, '\n' 을 줄 종결자로 사용하는 전통적인 Unix 스타일을 따릅니다. 등록된 방언 이름은 unix 입니다.

csv.DictWriter 에 필드 이름을 기재하기 위한 초기 행을 출력하는 새로운 메서드인 writeheader() 가 추가되었습니다:

>>> import csv, sys
>>> w = csv.DictWriter(sys.stdout, ['name', 'dept'], dialect='unix')
>>> w.writeheader()
"name","dept"
>>> w.writerows([
...     {'name': 'tom', 'dept': 'accounting'},
...     {'name': 'susan', 'dept': 'Salesl'}])
"tom","accounting"
"susan","sales"

(새로운 방언은 Jay Talbot이 bpo-5975 에서 제안하였고, 새로운 메서드는 Ed Abraham이 bpo-1537721 에서 제안하였습니다.)

contextlib

함수 데코레이터의 역할도 겸하는 컨텍스트 관리자 를 생성할 때 유용한 새롭고 놀라운 도구인 ContextDecorator 가 추가되었습니다.

편의를 위해 이 새로운 기능은 @~contextlib.contextmanager 에서 사용되므로 두 역할을 모두 지원하기 위해 추가적인 노력이 필요하지 않습니다.

기본 아이디어는 컨텍스트 관리자와 함수 데코레이터 모두를 사전 동작 및 후속 동작 래퍼로 사용할 수 있다는 것입니다. 컨텍스트 관리자는 with 문을 사용하여 일련의 구문을 감싸고, 함수 데코레이터는 함수 내에 포함된 일련의 구문을 감쌉니다. 따라서 때때로 두 역할 중 어느 하나에서든 사용 가능한 사전 또는 후속 동작 래퍼를 작성해야 할 필요가 있습니다.

예를 들어, 진입 시간과 종료 시간을 추적할 수 있는 로거로 함수나 구문 그룹을 감싸는 것이 유용할 때가 있습니다. 이 작업을 위해 함수 데코레이터와 컨텍스트 관리자를 모두 작성하는 대신, @~contextlib.contextmanager 를 사용하면 단일 정의로 두 기능을 모두 제공합니다:

from contextlib import contextmanager
import logging

logging.basicConfig(level=logging.INFO)

@contextmanager
def track_entry_and_exit(name):
    logging.info('Entering: %s', name)
    yield
    logging.info('Exiting: %s', name)

이전에는 이를 컨텍스트 관리자로만 사용할 수 있었습니다:

with track_entry_and_exit('widget loader'):
    print('Some time consuming activity goes here')
    load_widget()

이제 데코레이터로도 사용할 수 있습니다:

@track_entry_and_exit('widget loader')
def activity():
    print('Some time consuming activity goes here')
    load_widget()

두 역할을 동시에 수행하려다 보니 기술적인 한계가 발생합니다. 컨텍스트 관리자는 일반적으로 with 문에서 사용할 수 있는 인자를 반환할 수 있는 유연성이 있지만, 함수 데코레이터에는 그에 상응하는 기능이 없습니다.

위 예제에서 track_entry_and_exit 컨텍스트 관리자가 묶인 구문의 본문 내에서 사용하기 위해 로깅 인스턴스를 반환하는 깔끔한 방법이 없습니다.

(Michael Foord가 bpo-9110 에서 기여했습니다.)

decimal 및 fractions

Mark Dickinson은 서로 다른 숫자 데이터 형식이 실제 값이 동일할 때 동일한 해시 값을 갖도록 보장하는 우아하고 효율적인 방식을 설계했습니다 (bpo-8188):

assert hash(Fraction(3, 2)) == hash(1.5) == \
       hash(Decimal("1.5")) == hash(complex(1.5, 0))

해싱에 관한 일부 세부 정보는 새로운 어트리뷰트인 sys.hash_info 를 통해 공개됩니다. 이 속성은 해시 값의 비트 너비, 소수 모듈러스, infinitynan 의 해시 값, 그리고 숫자의 허수 부분에 사용되는 곱셈수를 기술합니다.

>>> sys.hash_info
sys.hash_info(width=64, modulus=2305843009213693951, inf=314159, nan=0, imag=1000003)

다양한 숫자 형식의 상호 운용성을 제한하기로 했던 초기 결정이 완화되었습니다. Decimal('1.1') + float('1.1') 과 같은 산술식에서 암시적인 혼합은 여전히 지원되지 않으며(권장되지도 않습니다), 이는 후자가 이진 부동 소수점을 구성하는 과정에서 정보를 손실하기 때문입니다. 그러나 기존 부동 소수점 값은 십진 또는 유리수 표현으로 정보 손실 없이 변환될 수 있으므로, 이를 생성자에 추가하고 혼합된 형식의 비교를 지원하는 것이 타당합니다.

  • decimal.Decimal 생성자가 이제 float 객체를 직접 수용하므로 더 이상 from_float() 메서드를 사용할 필요가 없습니다 (bpo-8257).

  • 이제 혼합된 형식을 비교하는 기능이 완전히 지원되어, Decimal 객체를 floatfractions.Fraction`과 직접 비교할 있습니다 (:issue:`2531, bpo-8188).

fractions.Fraction 에도 유사한 변경 사항이 적용되어 더 이상 from_float()from_decimal() 메서드를 사용할 필요가 없습니다 (bpo-8294):

>>> from decimal import Decimal
>>> from fractions import Fraction
>>> Decimal(1.1)
Decimal('1.100000000000000088817841970012523233890533447265625')
>>> Fraction(1.1)
Fraction(2476979795053773, 2251799813685248)

decimal 모듈의 또 다른 유용한 변경 사항은 Context.clamp 어트리뷰트가 이제 공개(public)되었다는 점입니다. 이는 IEEE 754에 명시된 십진 인터체인지 형식을 따르는 컨텍스트를 생성할 때 유용합니다 (참조: bpo-8540).

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

ftp

ftplib.FTP 클래스가 이제 컨텍스트 관리 프로토콜을 지원하여, 작업 완료 시 socket.error 예외를 무조건 처리하고 FTP 연결을 닫습니다:

>>> from ftplib import FTP
>>> with FTP("ftp1.at.proftpd.org") as ftp:
        ftp.login()
        ftp.dir()

'230 Anonymous login ok, restrictions apply.'
dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 .
dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 ..
dr-xr-xr-x   5 ftp      ftp          4096 May  6 10:43 CentOS
dr-xr-xr-x   3 ftp      ftp            18 Jul 10  2008 Fedora

mmap.mmapfileinput.input() 과 같은 다른 파일 유사 객체들도 자동 종료 컨텍스트 관리자 기능을 갖게 되었습니다:

with fileinput.input(files=('log1.txt', 'log2.txt')) as f:
    for line in f:
        process(line)

(Tarek Ziadé와 Giampaolo Rodolà가 bpo-4972 에서, Georg Brandl이 bpo-8046bpo-1286 에서 기여했습니다.)

FTP_TLS 클래스가 이제 context 매개변수를 수용하며, 이는 SSL 구성 옵션, 인증서 및 개인 키를 하나의 구조체에 묶을 수 있는 ssl.SSLContext 객체입니다.

(Giampaolo Rodolà가 bpo-8806 에서 기여했습니다.)

popen

os.popen()subprocess.Popen() 함수가 이제 파일 디스크립터를 자동으로 닫기 위해 with 문을 지원합니다.

(Antoine Pitrou와 Brian Curtin이 bpo-7461bpo-10554 에서 기여했습니다.)

선택

select 모듈이 새로운 상수 어트리뷰트인 PIPE_BUF 를 노출합니다. 이 값은 select.select() 가 파이프의 쓰기 준비 상태를 알릴 때, 블록되지 않음이 보장되는 최소 바이트 수를 나타냅니다.

>>> import select
>>> select.PIPE_BUF
512

(Unix 시스템에서 사용 가능합니다. Sébastien Sablé가 bpo-9862 에서 패치를 제공했습니다.)

gzip 및 zipfile

gzip.GzipFile 이 이제 추상 기본 클래스io.BufferedIOBase 를 구현합니다(truncate() 제외). 또한 peek() 메서드를 가지며, 탐색 불가능한(unseekable) 파일과 0으로 채워진(zero-padded) 파일 객체를 지원합니다.

The gzip module also gains the compress() and decompress() functions for easier in-memory compression and decompression. Keep in mind that text needs to be encoded as bytes before compressing and decompressing:

>>> import gzip
>>> s = 'Three shall be the number thou shalt count, '
>>> s += 'and the number of the counting shall be three'
>>> b = s.encode()                        # convert to utf-8
>>> len(b)
89
>>> c = gzip.compress(b)
>>> len(c)
77
>>> gzip.decompress(c).decode()[:42]      # decompress and convert to text
'Three shall be the number thou shalt count'

(Anand B. Pillai가 bpo-3488 에서, Antoine Pitrou, Nir Aides 및 Brian Curtin이 bpo-9962, bpo-1675951, bpo-7471bpo-2846 에서 기여했습니다.)

또한, zipfile.ZipExtFile 클래스가 내부적으로 아카이브 내에 저장된 파일을 표현하도록 재작업되었습니다. 새로운 구현은 훨씬 더 빠르며, 성능 향상을 위해 io.BufferedReader 객체로 감쌀 수 있습니다. 또한 read*와 *readline 호출이 섞여 있을 때 잘못된 결과가 나오던 문제를 해결했습니다.

(Nir Aides가 bpo-7610 에서 패치를 제출했습니다.)

타르파일

TarFile 클래스를 이제 컨텍스트 관리자로 사용할 수 있습니다. 또한, add() 메서드에 아카이브에 추가되는 파일을 제어하고 파일 메타데이터를 편집할 수 있게 하는 새로운 옵션인 filter 가 추가되었습니다.

The new filter option replaces the older, less flexible exclude parameter which is now deprecated. If specified, the optional filter parameter needs to be a keyword argument. The user-supplied filter function accepts a TarInfo object and returns an updated TarInfo object, or if it wants the file to be excluded, the function can return None:

>>> import tarfile, glob

>>> def myfilter(tarinfo):
...     if tarinfo.isfile():             # 실제 파일만 저장
...         tarinfo.uname = 'monty'      # 사용자 이름 가리기
...         return tarinfo

>>> with tarfile.open(name='myarchive.tar.gz', mode='w:gz') as tf:
...     for filename in glob.glob('*.txt'):
...         tf.add(filename, filter=myfilter)
...     tf.list()
-rw-r--r-- monty/501        902 2011-01-26 17:59:11 annotations.txt
-rw-r--r-- monty/501        123 2011-01-26 17:59:11 general_questions.txt
-rw-r--r-- monty/501       3514 2011-01-26 17:59:11 prion.txt
-rw-r--r-- monty/501        124 2011-01-26 17:59:11 py_todo.txt
-rw-r--r-- monty/501       1399 2011-01-26 17:59:11 semaphore_notes.txt

(Tarek Ziadé가 제안하고 Lars Gustäbel이 bpo-6856 에서 구현했습니다.)

hashlib

hashlib 모듈에 모든 구현체에서 존재가 보장되는 해싱 알고리즘과 현재 구현체에서 사용할 수 있는 알고리즘 목록을 나타내는 두 개의 새로운 상수 어트리뷰트가 추가되었습니다:

>>> import hashlib

>>> hashlib.algorithms_guaranteed
{'sha1', 'sha224', 'sha384', 'sha256', 'sha512', 'md5'}

>>> hashlib.algorithms_available
{'md2', 'SHA256', 'SHA512', 'dsaWithSHA', 'mdc2', 'SHA224', 'MD4', 'sha256',
'sha512', 'ripemd160', 'SHA1', 'MDC2', 'SHA', 'SHA384', 'MD2',
'ecdsa-with-SHA1','md4', 'md5', 'sha1', 'DSA-SHA', 'sha224',
'dsaEncryption', 'DSA', 'RIPEMD160', 'sha', 'MD5', 'sha384'}

(Carl Chenet이 bpo-7418 에서 제안했습니다.)

ast

ast 모듈은 Python 리터럴 구문을 사용하여 표현식 문자열을 안전하게 평가할 수 있는 훌륭한 범용 도구를 제공합니다. ast.literal_eval() 함수는 오용되기 쉬운 내장 eval() 함수의 보안 대안으로 기능합니다. Python 3.2에서는 지원되는 유형 목록에 string, bytes, number, tuple, list, dict, set, boolean 및 None 외에도 bytesset 리터럴을 추가했습니다.

>>> from ast import literal_eval

>>> request = "{'req': 3, 'func': 'pow', 'args': (2, 0.5)}"
>>> literal_eval(request)
{'args': (2, 0.5), 'req': 3, 'func': 'pow'}

>>> request = "os.system('do something harmful')"
>>> literal_eval(request)
Traceback (most recent call last):
  ...
ValueError: malformed node or string: <_ast.Call object at 0x101739a10>

(Benjamin Peterson과 Georg Brandl이 구현했습니다.)

os

운영체제마다 파일 이름과 환경 변수에 대해 다양한 인코딩을 사용합니다. os 모듈은 파일 이름을 인코딩하고 디코딩하기 위한 두 개의 새 함수인 fsencode()fsdecode() 를 제공합니다.

>>> import os
>>> filename = 'Sehenswürdigkeiten'
>>> os.fsencode(filename)
b'Sehensw\xc3\xbcrdigkeiten'

일부 운영체제는 환경 변수에서 인코딩된 바이트에 직접 접근하는 것을 허용합니다. 이 경우 os.supports_bytes_environ 상수가 참이 됩니다.

(사용 가능한 경우) 인코딩된 환경 변수에 직접 액세스하려면 새로운 os.getenvb() 함수를 사용하거나, os.environ 의 바이트 버전인 os.environb 를 사용하십시오.

(Victor Stinner가 기여했습니다.)

shutil 모듈

shutil.copytree() 함수에 두 가지 새로운 옵션이 추가되었습니다:

  • ignore_dangling_symlinks: symlinks=False 일 때, 함수가 심볼릭 링크 자체가 아닌 심볼릭 링크가 가리키는 파일을 복사하도록 합니다. 이 옵션은 대상 파일이 존재하지 않을 때 발생하는 오류를 무시합니다.

  • copy_function 은 파일을 복사하는 데 사용되는 콜러블입니다. 기본적으로 shutil.copy2() 가 사용됩니다.

(Tarek Ziadé가 기여했습니다.)

또한, shutil 모듈은 이제 zip파일, 압축되지 않은 tar 파일, gzipped tar 파일 및 bzipped tar 파일에 대한 archiving operations 를 지원합니다. 또한 추가적인 아카이빙 파일 형식(xz 압축 타르 파일 또는 사용자 정의 형식 등)을 등록하는 함수도 제공됩니다.

The principal functions are make_archive() and unpack_archive(). By default, both operate on the current directory (which can be set by os.chdir()) and on any sub-directories. The archive filename needs to be specified with a full pathname. The archiving step is non-destructive (the original files are left unchanged).

>>> import shutil, pprint

>>> os.chdir('mydata')  # 소스 디렉터리로 변경
>>> f = shutil.make_archive('/var/backup/mydata',
...                         'zip')      # 현재 디렉터리 아카이브 생성
>>> f                                   # 아카이브 이름 표시
'/var/backup/mydata.zip'
>>> os.chdir('tmp')                     # 압축 해제할 위치로 변경
>>> shutil.unpack_archive('/var/backup/mydata.zip')  # 데이터 복구

>>> pprint.pprint(shutil.get_archive_formats())  # 알려진 형식 표시
[('bztar', "bzip2'ed tar-file"),
 ('gztar', "gzip'ed tar-file"),
 ('tar', 'uncompressed tar file'),
 ('zip', 'ZIP file')]

>>> shutil.register_archive_format(     # 새로운 아카이브 형식 등록
...     name='xz',
...     function=xz.compress,           # 콜러블 아카이빙 함수
...     extra_args=[('level', 8)],      # 함수에 전달할 인자
...     description='xz compression'
... )

(Tarek Ziadé가 기여했습니다.)

sqlite3 모듈

sqlite3 모듈이 pysqlite 버전 2.6.0으로 업데이트되었습니다. 두 가지 새로운 기능이 추가되었습니다.

  • sqlite3.Connection.in_transit 속성은 커밋되지 않은 변경 사항에 대해 활성화된 트랜잭션이 있는 경우 True를 반환합니다.

  • sqlite3.Connection.enable_load_extension()sqlite3.Connection.load_extension() 메서드를 사용하여 .so 파일에서 SQLite 확장을 로드할 수 있습니다. 잘 알려진 확장 기능 중 하나는 SQLite와 함께 제공되는 전체 텍스트 검색(fulltext-search) 확장입니다.

(R. David Murray와 Shashwat Anand가 기여했습니다; bpo-8845.)

HTML

단 하나의 함수인 escape() 만 포함된 새로운 html 모듈이 도입되었습니다. 이 함수는 HTML 마크업의 예약된 문자를 이스케이프하는 데 사용됩니다.

>>> import html
>>> html.escape('x > 2 && x < 7')
'x &gt; 2 &amp;&amp; x &lt; 7'

소켓

socket 모듈에 두 가지 새로운 개선 사항이 반영되었습니다.

  • 소켓 객체에 이제 실제 파일 디스크립터를 닫지 않고 소켓을 닫은 상태로 만드는 detach() 메서드가 있습니다. 이 후자는 다른 용도로 재사용할 수 있습니다. (Antoine Pitrou 추가; bpo-8524.)

  • socket.create_connection() now supports the context management protocol to unconditionally consume socket.error exceptions and to close the socket when done. (Contributed by Giampaolo Rodolà; bpo-9794.)

ssl

ssl 모듈이 보안(암호화 및 인증) 인터넷 연결을 위한 일반적인 요구 사항을 충족하기 위해 여러 기능을 추가했습니다.

  • 새로운 클래스인 SSLContext 는 프로토콜 설정, 인증서, 개인 키 및 기타 다양한 옵션과 같은 지속적인 SSL 데이터를 위한 컨테이너 역할을 합니다. 이 클래스는 SSL 컨텍스트에서 SSL 소켓을 생성하는 wrap_socket() 메서드를 포함합니다.

  • 새로운 함수인 ssl.match_hostname`은 다른 프로토콜에도 적합한 HTTPS 규칙(:rfc:`2818())을 구현하여 상위 수준 프로토콜에 대한 서버 신원 확인을 지원합니다.

  • ssl.wrap_socket() 생성자 함수가 이제 ciphers 인자를 받습니다. ciphers 문자열은 OpenSSL 문서 에 설명된 형식을 사용하여 허용되는 암호화 알고리즘을 나열합니다.

  • 최신 버전의 OpenSSL과 링크될 때, ssl 모듈은 이제 TLS 프로토콜에 대한 Server Name Indication(SNI) 확장을 지원하여 단일 IP 포트에서 서로 다른 인증서를 사용하는 여러 &quot;가상 호스트&quot;를 허용합니다. 이 확장은 클라이언트 모드에서만 지원되며, ssl.SSLContext.wrap_socket()server_hostname 인자를 전달하여 활성화됩니다.

  • ssl 모듈에 안전하지 않고 오래된 SSLv2 프로토콜을 비활성화하는 OP_NO_SSLv2 를 포함한 다양한 옵션이 추가되었습니다.

  • 이제 확장이 모든 OpenSSL 사이퍼 및 다이제스트 알고리즘을 로드합니다. 일부 SSL 인증서를 확인할 수 없는 경우 &quot;알려지지 않은 알고리즘&quot; 오류로 보고됩니다.

  • 사용 중인 OpenSSL 버전은 이제 모듈 속성인 ssl.OPENSSL_VERSION (문자열), ssl.OPENSSL_VERSION_INFO (5개 요소 튜플), 그리고 ssl.OPENSSL_VERSION_NUMBER (정수)를 사용하여 확인할 수 있습니다.

(Antoine Pitrou가 bpo-8850, bpo-1589, bpo-8322, bpo-5639, bpo-4870, bpo-8484, 그리고 bpo-8321 에서 기여했습니다.)

nntp

nntplib 모듈은 더 나은 바이트 및 텍스트 의미론과 더 실용적인 API를 갖춘 개편된 구현을 제공합니다. 이러한 개선 사항은 자체적으로도 일부 기능이 제대로 작동하지 않았던 Python 3.1의 nntplib 버전과의 호환성을 깨뜨립니다.

내재적 연결( nntplib.NNTP_SSL 사용)과 명시적 연결(nntplib.NNTP.starttls() 사용) 모두를 통한 보안 연결 지원이 추가되었습니다.

(Antoine Pitrou가 bpo-9360 에서, Andrew Vant가 bpo-1926 에서 기여했습니다.)

인증서

http.client.HTTPSConnection, urllib.request.HTTPSHandler, 그리고 urllib.request.urlopen() 은 이제 공개적인 HTTPS 사용에서 권장되는 대로 일련의 인증 기관(Certificate Authorities)에 대한 서버 인증서 확인이 가능하도록 선택적 인수를 받습니다.

(Antoine Pitrou가 추가했습니다, bpo-9003.)

imaplib

새로운 imaplib.IMAP4.starttls 메서드를 통해 표준 IMAP4 연결에 대한 명시적 TLS 지원이 추가되었습니다.

(Lorenzo M. Catucci와 Antoine Pitrou가 기여했습니다, bpo-4471.)

http.client

http.client 모듈에 여러 가지 작은 API 개선이 있었습니다. 오래된 방식의 HTTP 0.9 단순 응답은 더 이상 지원되지 않으며 모든 클래스에서 strict 매개변수가 폐지되었습니다.

HTTPConnectionHTTPSConnection 클래스에 이제 HTTP 연결이 시작되는 위치를 나타내는 (호스트, 포트) 튜플인 source_address 매개변수가 추가되었습니다.

HTTPSConnection 에 인증서 확인 및 HTTPS 가상 호스트 지원이 추가되었습니다.

연결 객체의 request() 메서드는 선택적 body 인수를 허용하여 요청 내용을 제공하는 데 file object 를 사용할 수 있게 했습니다. 편리하게도, body 인자는 이제 명시적인 Content-Length 헤더가 포함되어 있는 경우 iterable 객체도 받아들입니다. 이 확장된 인터페이스는 이전보다 훨씬 유연합니다.

프록시 서버를 통해 HTTPS 연결을 수립하려면, HTTP Connect 터널링을 위한 호스트와 포트를 설정하는 새로운 set_tunnel() 메서드가 추가되었습니다.

http.server`의 동작과 일치하도록 HTTP 클라이언트 라이브러리도 이제 헤더를 ISO-8859-1 (Latin-1) 인코딩으로 처리합니다. 이미 수신 헤더에 대해 그렇게 수행하고 있었으므로, 이제 송수신 트래픽 모두에서 일관된 동작을 보입니다. (Armin Ronacher의 작업 내용 참조: :issue:`10980.)

unittest`

unittest 모듈은 패키지에 대한 테스트 검색 지원, 대화형 프롬프트에서의 보다 쉬운 실험 기능, 새로운 테스트 케이스 메서드, 테스트 실패 시 개선된 진단 메시지 및 더 나은 메서드 이름 등 다양한 개선 사항을 포함합니다.

  • 명령줄 호출인 python -m unittest 는 이제 특정 테스트를 실행할 때 모듈 이름 대신 파일 경로를 수용할 수 있습니다(bpo-10620). 새로운 테스트 검색 기능을 통해 패키지 내의 테스트를 찾을 수 있으며, 최상위 디렉터리에서 가져올 수 있는 모든 테스트를 찾아냅니다. 최상위 디렉터리는 -t 옵션으로, 파일 매칭 패턴은 -p 로, 탐색을 시작할 디렉터리는 -s 로 지정할 수 있습니다.

    $ python -m unittest discover -s my_proj_dir -p "_test.py"
    

    (Michael Foord가 기여했습니다.)

  • unittest.TestCase 클래스를 인수 없이도 인스턴스화할 수 있게 되어 대화형 프롬프트에서 실험하기가 더 쉬워졌습니다:

    >>> from unittest import TestCase
    >>> TestCase().assertEqual(pow(2, 3), 8)
    

    (Michael Foord가 기여했습니다.)

  • unittest 모듈에는 테스트 대상 코드에 의해 특정 경고 유형이 발생하는지 확인하는 두 가지 새 메서드인 assertWarns()assertWarnsRegex() 가 추가되었습니다.

    with self.assertWarns(DeprecationWarning):
        legacy_function('XYZ')
    

    (Antoine Pitrou가 기여했습니다, bpo-9754.)

    또 다른 새 메서드인 assertCountEqual() 은 두 개의 반복 가능한 객체(iterable)를 비교하여 요소의 개수가 동일한지 확인하는 데 사용됩니다 (순서에 상관없이 동일한 요소가 동일한 횟수로 존재하는지 여부).

    def test_anagram(self):
        self.assertCountEqual('algorithm', 'logarithm')
    

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

  • unittest 모듈의 주요 기능 중 하나는 테스트 실패 시 유의미한 진단 정보를 생성하는 것입니다. 가능한 경우, 출력 결과의 차이(diff)와 함께 실패 내용이 기록됩니다. 이는 특히 실패한 테스트 실행의 로그 파일을 분석할 때 매우 유용합니다. 다만 diff가 때때로 너무 방대할 수 있으므로, 표시되는 diff의 최대 길이를 설정하는 새로운 maxDiff 어트리뷰트가 추가되었습니다.

  • 또한, 이 모듈의 메서드 이름들이 대거 정리되었습니다.

    예를 들어, assertRegex() 는 기존에 assertRegexpMatches() 였으나, 테스트가 re.match() 가 아닌 re.search() 를 사용함에도 이름이 잘못되어 있었기 때문에 변경되었습니다. 정규 표현식을 사용하는 다른 메서드들도 “Regexp” 대신 짧은 형태인 “Regex”로 명칭이 바뀌었습니다. 이는 다른 unittest 구현체에서 사용하는 이름과 일치하며, Python의 기존 re 모듈 명칭과도 일치하고, 모호하지 않은 카멜 케이스(camel-casing)를 따릅니다.

    (Raymond Hettinger가 제안하고 Ezio Melotti가 구현했습니다.)

  • 일관성을 높이기 위해 오랫동안 사용되어 온 일부 메서드 별칭을 권장되는 이름으로 대체하며 더 이상 사용하지 않기로(deprecated) 했습니다:

    기존 이름

    권장되는 이름

    assert_()

    assertTrue()

    assertEquals()

    assertEqual()

    assertNotEquals()

    assertNotEqual()

    assertAlmostEquals()

    assertAlmostEqual()

    assertNotAlmostEquals()

    assertNotAlmostEqual()

    마찬가지로, Python 3.1에서 폐지된 TestCase.fail* 메서드들은 Python 3.3에서 제거될 예정입니다.

    (Ezio Melotti가 기여함; bpo-9424.)

  • assertDictContainsSubset() 메서드는 인자 순서가 잘못 구현되어 폐지되었습니다. 이로 인해 TestCase().assertDictContainsSubset({'a':1, 'b':2}, {'a':1}) 와 같은 테스트가 실패하는 등 디버그하기 어려운 착시 현상이 발생했습니다.

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

random

random 모듈의 정수 메서드들이 이제 더 나은 균일 분포를 생성하도록 개선되었습니다. 이전에는 int(n*random()) 을 사용하여 선택값을 계산했는데, 이 경우 n 이 2의 거듭제곱이 아닐 때 약간의 편향이 발생했습니다. 이제는 다음 2의 거듭제곱까지의 범위에서 여러 번 선택을 수행하고, 그 결과가 0 <= x < n 범위 내에 있을 때만 유지합니다. 영향을 받는 함수 및 메서드는 randrange(), randint(), choice(), shuffle(), sample() 입니다.

(Raymond Hettinger가 기여함; bpo-9025.)

poplib

POP3_SSL 클래스가 이제 context 파라미터를 수용합니다. 이는 ssl.SSLContext 객체로, SSL 구성 옵션, 인증서 및 개인 키를 하나의(수명이 긴) 구조체에 묶어서 처리할 수 있게 해줍니다.

(Giampaolo Rodolà가 기여함; bpo-8807.)

asyncore

asyncore.dispatcher`가 이제 새로운 원격 엔드포인트와 연결이 실제로 수립되었을 호출되는 ``(sock, addr)` 쌍을 반환하는 handle_accepted() 메서드를 제공합니다. 이는 기존의 handle_accept`를 대체하기 위한 것이며, 사용자가 :meth:()!accept`를 직접 호출하는 것을 방지합니다.

(Giampaolo Rodolà가 기여함; bpo-6706.)

임시 파일

tempfile 모듈에 임시 디렉터리를 쉽게 확정적으로 정리해 주는 새로운 컨텍스트 관리자인 TemporaryDirectory 가 추가되었습니다:

with tempfile.TemporaryDirectory() as tmpdirname:
    print('created temporary dir:', tmpdirname)

(Neil Schemenauer와 Nick Coghlan이 기여함; bpo-5178.)

inspect 메듈

  • inspect 모듈에 제너레이터-이터레이터의 현재 상태를 쉽게 식별하는 새로운 함수인 getgeneratorstate() 가 추가되었습니다:

    >>> from inspect import getgeneratorstate
    >>> def gen():
    ...     yield 'demo'
    ...
    >>> g = gen()
    >>> getgeneratorstate(g)
    'GEN_CREATED'
    >>> next(g)
    'demo'
    >>> getgeneratorstate(g)
    'GEN_SUSPENDED'
    >>> next(g, None)
    >>> getgeneratorstate(g)
    'GEN_CLOSED'
    

    (Rodolpho Eckhardt와 Nick Coghlan이 기여함; bpo-10220.)

  • 동적 어트리뷰트를 활성화할 가능성 없이 조회를 지원하기 위해, inspect 모듈에 새로운 함수인 getattr_static() 이 추가되었습니다. hasattr() 과 달리 이것은 완전한 읽기 전용 검색이며, 검색 중에 상태를 변경하지 않음을 보장합니다:

    >>> class A:
    ...     @property
    ...     def f(self):
    ...         print('Running')
    ...         return 10
    ...
    >>> a = A()
    >>> getattr(a, 'f')
    Running
    10
    >>> inspect.getattr_static(a, 'f')
    <property object at 0x1022bd788>
    

(Michael Foord가 기여했습니다.)

pydoc

pydoc 모듈은 이제 대폭 개선된 웹 서버 인터페이스와 해당 서버를 표시하기 위해 브라우저 창을 자동으로 여는 새로운 명령줄 옵션 -b 를 제공합니다:

$ pydoc3.2 -b

(Ron Adam이 기여함; bpo-2001.)

dis

dis 모듈에 코드를 조사하기 위한 두 가지 새로운 함수인 code_info()show_code() 가 추가되었습니다. 둘 다 제공된 함수, 메서드, 소스 코드 문자열 또는 코드 객체에 대한 상세한 코드 객체 정보를 제공합니다. 전자는 문자열을 반환하고 후자는 이를 출력합니다:

>>> import dis, random
>>> dis.show_code(random.choice)
Name:              choice
Filename:          /Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/random.py
Argument count:    2
Kw-only arguments: 0
Number of locals:  3
Stack size:        11
Flags:             OPTIMIZED, NEWLOCALS, NOFREE
Constants:
   0: 'Choose a random element from a non-empty sequence.'
   1: 'Cannot choose from an empty sequence'
Names:
   0: _randbelow
   1: len
   2: ValueError
   3: IndexError
Variable names:
   0: self
   1: seq
   2: i

또한, dis() 함수가 이제 문자열 인수를 받아들여 일반적인 관용구인 dis(compile(s, '', 'eval'))dis(s) 로 단축할 수 있습니다:

>>> dis('3*x+1 if x%2==1 else x//2')
  1           0 LOAD_NAME                0 (x)
              3 LOAD_CONST               0 (2)
              6 BINARY_MODULO
              7 LOAD_CONST               1 (1)
             10 COMPARE_OP               2 (==)
             13 POP_JUMP_IF_FALSE       28
             16 LOAD_CONST               2 (3)
             19 LOAD_NAME                0 (x)
             22 BINARY_MULTIPLY
             23 LOAD_CONST               1 (1)
             26 BINARY_ADD
             27 RETURN_VALUE
        >>   28 LOAD_NAME                0 (x)
             31 LOAD_CONST               0 (2)
             34 BINARY_FLOOR_DIVIDE
             35 RETURN_VALUE

이러한 개선사항들을 종합하면, CPython의 구현 방식을 탐색하고 언어 구문이 내부적으로 어떻게 작동하는지 직접 확인하기가 더 쉬워집니다.

(Nick Coghlan이 기여함; bpo-9147.)

dbm

모든 데이터베이스 모듈이 이제 get()setdefault() 메서드를 지원합니다.

(Ray Allen의 제안으로 추가됨; bpo-9523.)

ctypes

새로운 타입인 ctypes.c_ssize_t 는 C ssize_t 데이터형을 나타냅니다.

site

site 모듈에 특정 파이썬 설치의 세부 사항을 보고하는 데 유용한 세 가지 새로운 함수가 추가되었습니다.

  • getsitepackages() 는 모든 전역 site-packages 디렉터리를 나열합니다.

  • getuserbase() 는 데이터가 저장될 수 있는 사용자의 기본 디렉터리를 보고합니다.

  • getusersitepackages() 는 사용자 전용 site-packages 디렉터리 경로를 보여줍니다.

>>> import site
>>> site.getsitepackages()
['/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages',
 '/Library/Frameworks/Python.framework/Versions/3.2/lib/site-python',
 '/Library/Python/3.2/site-packages']
>>> site.getuserbase()
'/Users/raymondhettinger/Library/Python/3.2'
>>> site.getusersitepackages()
'/Users/raymondhettinger/Library/Python/3.2/lib/python/site-packages'

편의를 위해, site의 일부 기능을 명령 줄에서 직접 사용할 수 있습니다:

$ python -m site --user-base
/Users/raymondhettinger/.local
$ python -m site --user-site
/Users/raymondhettinger/.local/lib/python3.2/site-packages

(Tarek Ziadé가 기여함; bpo-6693.)

sysconfig 모듈

새로운 sysconfig 모듈을 사용하면 플랫폼 및 설치 환경에 따라 달라지는 설치 경로와 구성 변수를 쉽게 파악할 수 있습니다.

이 모듈은 플랫폼 및 버전 정보를 위한 간단한 접근 함수를 제공합니다:

  • get_platform()linux-i586 또는 macosx-10.6-ppc 와 같은 값을 반환합니다.

  • get_python_version() 은 “3.2”와 같은 파이썬 버전 문자열을 반환합니다.

또한 이 모듈은 distutils 에서 사용하는 7가지 명명된 스킴 중 하나에 해당하는 경로와 변수에 접근할 수 있게 해줍니다. 해당 스킴은 posix_prefix, posix_home, posix_user, nt, nt_user, os2, os2_home 을 포함합니다.

또한 편리한 명령 줄 인터페이스가 있습니다:

C:\Python32>python -m sysconfig
Platform: "win32"
Python version: "3.2"
Current installation scheme: "nt"

Paths:
        data = "C:\Python32"
        include = "C:\Python32\Include"
        platinclude = "C:\Python32\Include"
        platlib = "C:\Python32\Lib\site-packages"
        platstdlib = "C:\Python32\Lib"
        purelib = "C:\Python32\Lib\site-packages"
        scripts = "C:\Python32\Scripts"
        stdlib = "C:\Python32\Lib"

Variables:
        BINDIR = "C:\Python32"
        BINLIBDEST = "C:\Python32\Lib"
        EXE = ".exe"
        INCLUDEPY = "C:\Python32\Include"
        LIBDEST = "C:\Python32\Lib"
        SO = ".pyd"
        VERSION = "32"
        abiflags = ""
        base = "C:\Python32"
        exec_prefix = "C:\Python32"
        platbase = "C:\Python32"
        prefix = "C:\Python32"
        projectbase = "C:\Python32"
        py_version = "3.2"
        py_version_nodot = "32"
        py_version_short = "3.2"
        srcdir = "C:\Python32"
        userbase = "C:\Documents and Settings\Raymond\Application Data\Python"

(Tarek Ziadé에 의해 Distutils에서 이동됨.)

pdb

pdb 디버거 모듈이 여러 사용성 개선을 거쳤습니다:

  • pdb.py`에 이제 :file:.pdbrc` 스크립트 파일에 명시된 대로 명령을 실행하는 -c 옵션이 추가되었습니다.

  • .pdbrc 스크립트 파일에 디버깅을 계속하는 continuenext 명령을 포함할 수 있습니다.

  • Pdb 클래스 생성자가 이제 nosigint 인수를 수용합니다.

  • 새로운 명령: 소스 코드를 나열하는 l(list), ll(long list)source.

  • 새로운 명령: 값이 변경되었을 때 표현식의 값을 표시하거나 숨기는 displayundisplay.

  • 새로운 명령: 현재 범위 내에서 발견된 전역 및 지역 변수를 포함하는 대화형 인터프리터를 시작하는 interact.

  • 중단점을 중단점 번호로 해제할 수 있습니다.

(Georg Brandl, Antonio Cuni, Ilya Sandler가 기여함.)

configparser

configparser 모듈은 기본 파서와 지원되는 INI 구문의 사용성 및 예측 가능성을 개선하기 위해 수정되었습니다. 기존의 ConfigParser 클래스는 SafeConfigParser 로 대체되었으며, 이는 다시 ConfigParser 로 이름이 변경되었습니다. 인라인 주석 지원은 이제 기본적으로 비활성화되며, 단일 구성 소스에서 섹션 또는 옵션의 중복은 허용되지 않습니다.

구성 파서가 매핑 프로토콜에 기반한 새로운 API를 얻었습니다:

>>> parser = ConfigParser()
>>> parser.read_string("""
... [DEFAULT]
... location = upper left
... visible = yes
... editable = no
... color = blue
...
... [main]
... title = Main Menu
... color = green
...
... [options]
... title = Options
... """)
>>> parser['main']['color']
'green'
>>> parser['main']['editable']
'no'
>>> section = parser['options']
>>> section['title']
'Options'
>>> section['title'] = 'Options (editable: %(editable)s)'
>>> section['title']
'Options (editable: no)'

새로운 API는 기존 API를 기반으로 구현되었으므로, 커스텀 파서 서브 클래스는 수정 없이 이를 사용할 수 있습니다.

구성 파서가 수용하는 INI 파일 구조를 이제 사용자 정의할 수 있습니다. 사용자는 다른 옵션/값 구분자와 주석 접두사를 지정하거나, DEFAULT 섹션의 이름을 변경하거나, 보간 구문을 전환할 수 있습니다.

추가적인 보간 핸들러인 ExtendedInterpolation 을 포함하여 플러그형 보간 기능을 지원합니다:

>>> parser = ConfigParser(interpolation=ExtendedInterpolation())
>>> parser.read_dict({'buildout': {'directory': '/home/ambv/zope9'},
...                   'custom': {'prefix': '/usr/local'}})
>>> parser.read_string("""
... [buildout]
... parts =
...   zope9
...   instance
... find-links =
...   ${buildout:directory}/downloads/dist
...
... [zope9]
... recipe = plone.recipe.zope9install
... location = /opt/zope
...
... [instance]
... recipe = plone.recipe.zope9instance
... zope9-location = ${zope9:location}
... zope-conf = ${custom:prefix}/etc/zope.conf
... """)
>>> parser['buildout']['find-links']
'\n/home/ambv/zope9/downloads/dist'
>>> parser['instance']['zope-conf']
'/usr/local/etc/zope.conf'
>>> instance = parser['instance']
>>> instance['zope-conf']
'/usr/local/etc/zope.conf'
>>> instance['zope9-location']
'/opt/zope'

읽기 작업 시 인코딩 지정, get 함수에 대한 기본값(fallback) 설정, 또는 딕셔너리 및 문자열에서 직접 읽기 등 여러 작은 기능들도 도입되었습니다.

(모든 변경 사항은 Łukasz Langa가 기여함.)

urllib.parse

urllib.parse 모듈에 대한 여러 사용성 개선이 이루어졌습니다.

urlparse() 함수는 이제 RFC 2732 에 기술된 바와 같이 IPv6 주소를 지원합니다:

>>> import urllib.parse
>>> urllib.parse.urlparse('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]/foo/')
ParseResult(scheme='http',
            netloc='[dead:beef:cafe:5417:affe:8FA3:deaf:feed]',
            path='/foo/',
            params='',
            query='',
            fragment='')

The urldefrag() function now returns a named tuple:

>>> r = urllib.parse.urldefrag('http://python.org/about/#target')
>>> r
DefragResult(url='http://python.org/about/', fragment='target')
>>> r[0]
'http://python.org/about/'
>>> r.fragment
'target'

또한, urlencode() 함수는 이제 더욱 유연해져서 query 인자로 문자열이나 바이트 타입을 모두 수용합니다. 문자열인 경우, safe, encoding, error 파라미터가 인코딩을 위해 quote_plus() 로 전달됩니다:

>>> urllib.parse.urlencode([
...      ('type', 'telenovela'),
...      ('name', '¿Dónde Está Elisa?')],
...      encoding='latin-1')
'type=telenovela&name=%BFD%F3nde+Est%E1+Elisa%3F'

ASCII로 인코딩된 바이트열 구문 분석 에서 자세히 설명한 바와 같이, 모든 urllib.parse 함수는 일반 문자열과 혼합되지 않는 한 입력으로 ASCII 인코딩된 바이트 문자열을 수용합니다. 파라미터로 ASCII 인코딩된 바이트 문자열이 주어지면 반환 타입 또한 ASCII 인코딩된 바이트 문자열이 됩니다:

>>> urllib.parse.urlparse(b'http://www.python.org:80/about/')
ParseResultBytes(scheme=b'http', netloc=b'www.python.org:80',
                 path=b'/about/', params=b'', query=b'', fragment=b'')

(Nick Coghlan, Dan Mahn, Senthil Kumaran의 작업 포함; bpo-2987, bpo-5468, bpo-9873.)

mailbox

Thanks to a concerted effort by R. David Murray, the mailbox module has been fixed for Python 3.2. The challenge was that mailbox had been originally designed with a text interface, but email messages are best represented with bytes because various parts of a message may have different encodings.

이 솔루션은 임의의 이메일 메시지를 파싱하기 위해 email 패키지의 바이너리 지원을 활용했습니다. 또한, 이 솔루션을 구현하는 과정에서 여러 API 변경이 필요했습니다.

예상대로, mailbox.Mailbox 객체를 위한 add() 메서드가 이제 바이너리 입력을 수용합니다.

StringIO 및 텍스트 파일 입력은 사용 중단(deprecated)되었습니다. 또한, 문자열 입력 시 비-ASCII 문자를 사용하면 조기에 오류가 발생합니다. 이전에는 이메일을 처리하는 나중 단계에서 오류가 발생했습니다.

바이너리 출력도 지원됩니다. get_file() 메서드는 이제 파일을 바이너리 모드로 반환합니다 (이전에는 텍스트 모드로 잘못 설정되곤 했습니다). 또한, 주어진 key 에 해당하는 메시지의 bytes 표현을 반환하는 새로운 get_bytes() 메서드도 추가되었습니다.

구형 API의 get_string() 메서드를 사용하여 비바이너리 출력을 얻는 것도 여전히 가능하지만, 이 방식은 그리 유용하지 않습니다. 대신, Message 객체에서 메시지를 추출하거나 바이너리 입력으로부터 불러오는 것이 가장 좋습니다.

(R. David Murray가 기여하였으며, Steffen Daode Nurpmeso의 노력과 Victor Stinner의 초기 패치가 bpo-9124 에서 포함되었습니다.)

turtledemo

turtle 모듈의 데모 코드가 Demo 디렉토리에서 메인 라이브러리로 이동되었습니다. 이 코드는 생동감 넘치는 화면을 포함하는 10여 개의 샘플 스크립트를 포함합니다. sys.path 에 위치하므로 이제 명령줄에서 직접 실행할 수 있습니다:

$ python -m turtledemo

(Alexander Belopolsky에 의해 bpo-10199 에서 Demo 디렉토리로부터 이동됨.)

멀티스레딩

  • 동시에 실행되는 파이썬 스레드의 실행을 직렬화하는 메커니즘(일반적으로 GIL 또는 Global Interpreter Lock으로 알려짐)이 재작성되었습니다. 주요 목표는 더 예측 가능한 전환 간격을 확보하고, 잠금 경합 및 이어지는 시스템 호출 횟수로 인한 오버헤드를 줄이는 것이었습니다. 스레드 전환을 허용하기 위한 “확인 간격(check interval)” 개념을 폐기하고 초 단위로 표현되는 절대 지속 시간으로 대체했습니다. 이 매개변수는 sys.setswitchinterval() 을 통해 조정할 수 있으며, 현재 기본값은 5밀리초입니다.

    구현에 관한 자세한 내용은 python-dev 메일링 리스트 메시지 에서 확인할 수 있습니다(단, 이 메시지에 노출된 “우선순위 요청”은 포함되지 않았습니다).

    (Antoine Pitrou가 기여했습니다.)

  • 일반 및 재귀 록이 이제 acquire() 메서드에서 선택적인 timeout 인수를 허용합니다. (Antoine Pitrou가 기여; bpo-7316.)

  • 마찬가지로, threading.Semaphore.acquire`도 *timeout* 인자를 갖게 되었습니다. (Torsten Landschoff가 기여; :issue:`850728().)

  • Pthreads를 사용하는 플랫폼에서 일반 및 재귀 록 획득이 이제 시그널에 의해 인터럽트될 수 있습니다. 이는 록을 획득하는 동안 데드락(deadlock)이 발생하는 파이썬 프로그램이 프로세스에 SIGINT를 반복적으로 전송(대부분의 셸에서 Ctrl+C`를 누름)하여 성공적으로 종료될 있음을 의미합니다. (Reid Kleckner가 기여; :issue:`8844.)

최적화들`

다수의 소규모 성능 개선 사항이 추가되었습니다:

  • 파이썬의 피프홀(peephole) 최적화기가 이제 x in {1, 2, 3} 과 같은 패턴을 상수 집합에 대한 멤버십 테스트로 인식합니다. 최적화기는 setfrozenset 으로 다시 캐스팅하고 미리 생성된 상수를 저장합니다.

    속도 저하 문제가 해결됨에 따라 이제 집합 표기법을 사용하여 멤버십 테스트를 작성하는 것이 실용적입니다. 이 방식은 의미론적으로 명확할 뿐만 아니라 작동 속도도 빠릅니다.

    extension = name.rpartition('.')[2]
    if extension in {'xml', 'html', 'xhtml', 'css'}:
        handle(name)
    

    (Dave Malcolm이 패치와 추가 테스트를 기여하였습니다; bpo-6690.)

  • pickle 모듈을 사용하여 데이터를 직렬화하고 역직렬화하는 속도가 몇 배 더 빨라졌습니다.

    (Alexandre Vassalotti, Antoine Pitrou 및 Unladen Swallow 팀이 bpo-9410bpo-3873 에서 기여하였습니다.)

  • list.sort()sorted() 에서 사용되는 Timsort 알고리즘 <https://en.wikipedia.org/wiki/Timsort>_이 이제 key function 과 함께 호출될 때 더 빠르고 적은 메모리를 소모합니다. 이전에는 리스트의 모든 요소가 각 요소와 관련된 키 값을 기억하는 임시 객체로 래핑되었습니다. 이제는 두 개의 키와 값 배열이 병렬로 정렬됩니다. 이를 통해 정렬 래퍼에 소비되는 메모리가 절약되고, 비교를 위임하는 데 소모되는 시간이 단축됩니다.

    (Daniel Stutzbach가 bpo-9915 에서 패치를 제공하였습니다.)

  • 여러 키에 대해 동일한 문자열이 반복되는 경우 JSON 디코딩 성능이 향상되고 메모리 소비가 줄어들었습니다. 또한, 이제 sort_keys 인자가 참(true)일 때 JSON 인코딩 시 C 기반의 속도 향상이 적용됩니다.

    (Antoine Pitrou가 bpo-7451 에서, Raymond Hettinger와 Antoine Pitrou가 bpo-10314 에서 기여하였습니다.)

  • 재귀적 록(threading.RLock() API로 생성됨)은 이제 C 구현의 혜택을 받아 일반 록만큼 빠르며, 이전 순수 파이썬 구현보다 10배에서 15배 더 빠릅니다.

    (Antoine Pitrou가 기여하였습니다; bpo-3001.)

  • stringlib의 빠른 검색(fast-search) 알고리즘이 이제 bytes, bytearraystr 객체에 대한 split(), rsplit(), splitlines()replace() 메서드에서 사용됩니다. 마찬가지로, 이 알고리즘은 rfind(), rindex(), rsplit()rpartition() 에서도 사용됩니다.

    (Florent Xicluna가 bpo-7622bpo-7462 에서 패치를 제공하였습니다.)

  • 정수를 문자열로 변환할 때 이제 한 번에 두 개의 “자리(digit)”를 처리하여 나눗셈 및 나머지 연산 횟수를 줄였습니다.

    (Gawain Bolton, Mark Dickinson, Victor Stinner에 의해 bpo-6713 에서 처리됨.)

기타 몇 가지 소규모 최적화가 이루어졌습니다. 한 피연산자가 다른 쪽보다 훨씬 클 때 집합 차집합 연산이 더 빠르게 실행됩니다(Andress Bennetts, bpo-8685). array.repeat() 메서드의 구현이 개선되었습니다(bpo-1569291, Alexander Belopolsky). BaseHTTPRequestHandler`의 버퍼링 효율이 향상되었습니다(:issue:`3709, Andrew Schaaf). operator.attrgetter() 함수의 속도가 향상되었고(bpo-10160, Christos Georgiou), ConfigParser`가 여러 줄에 걸친 인수를 약간 빠르게 로드합니다(:issue:`7113, Łukasz Langa).

유니코드(Unicode)

파이썬이 Unicode 6.0.0 로 업데이트되었습니다.

또한 업데이트된 표준은 두 개의 칸나다(Kannada) 문자(U+0CF1, U+0CF2)와 하나의 새로운 타이루(New Tai Lue) 숫자 문자(U+19DA)의 특성을 변경하여, 전자는 식별자로 사용할 수 있게 되었고 후자는 제외되었습니다. 자세한 정보는 Unicode Character Database Changes 를 참조하십시오.

코덱

cp720 아랍어 DOS 인코딩에 대한 지원이 추가되었습니다. (bpo-1616979.)

MBCS 인코딩이 더 이상 오류 처리기(error handler) 인자를 무시하지 않습니다. 기본값인 strict 모드에서, 인코딩할 수 없는 바이트 시퀀스를 만나면 UnicodeDecodeError 를 발생시키고, 인코딩할 수 없는 문자에 대해서는 UnicodeEncodeError 를 발생시킵니다.

MBCS 코덱은 디코딩 시 'strict'''ignore' 오류 처리기를 지원하며, 인코딩 시 'strict''replace' 를 지원합니다.

Python3.1의 MBCS 인코딩을 모방하려면 디코딩 시 'ignore'``를, 인코딩 ``'replace' 처리를 선택하십시오.

Mac OS X에서 파이썬은 명령줄 인수를 로케일 인코딩 대신 'utf-8' 으로 디코딩합니다.

기본적으로 tarfile`은 Windows에서 `’mbcs’`` 대신 'utf-8' 인코딩을 사용하며, 모든 운영 체제에서 'surrogateescape' 오류 처리기를 사용합니다.

문서

문서가 계속 개선되고 있습니다.

  • 내장 함수 와 같은 긴 섹션 상단에 빠른 링크 표가 추가되었습니다. itertools 의 경우, 전체 문서를 읽지 않고도 개요를 파악하고 기억을 되살릴 수 있도록 체크시트 스타일의 요약표가 함께 제공됩니다.

  • 어떤 경우에는 파이썬 순수 소스 코드가 문서에 유용한 참고 자료가 될 수 있으므로, 이제 많은 모듈에서 최신 버전의 소스 코드에 대한 빠른 링크를 제공합니다. 예를 들어, functools 모듈 설명서 상단에는 다음과 같이 표시된 빠른 링크가 있습니다:

    소스 코드 Lib/functools.py.

    (Raymond Hettinger가 기여하였습니다. 관련 근거는 rationale 를 참조하십시오.)

  • 이제 문서에 더 많은 예제와 레시피가 포함되어 있습니다. 특히, re 모듈에는 상세한 섹션인 정규식 예제 가 추가되었습니다. 마찬가지로, itertools 모듈은 새로운 Itertools 조리법 를 통해 지속적으로 업데이트되고 있습니다.

  • datetime 모듈에 파이썬 순수 언어(pure Python)로 작성된 보조 구현이 추가되었습니다. 기능은 변경되지 않았으며, 읽기 더 쉬운 대체 구현을 제공할 뿐입니다.

    (Alexander Belopolsky가 bpo-9528 에서 기여하였습니다.)

  • 관리되지 않는 Demo 디렉토리가 삭제되었습니다. 일부 데모는 문서에 통합되었고, 일부는 Tools/demo 디렉토리로 이동되었으며, 나머지는 완전히 제거되었습니다.

    (Georg Brandl이 bpo-7962 에서 기여하였습니다.)

IDLE

  • 포맷 메뉴에 끝에 오는 공백을 제거하여 소스 파일을 정리하는 옵션이 추가되었습니다.

    (Raymond Hettinger가 기여하였습니다; bpo-5150.)

  • Mac OS X의 IDLE가 이제 Carbon AquaTk와 Cocoa AquaTk 모두에서 작동합니다.

    (Kevin Walzer, Ned Deily 및 Ronald Oussoren이 bpo-6075 에서 기여하였습니다.)

코드 저장소

https://svn.python.org에 있는 기존 Subversion 코드 저장소 외에도, 이제 https://hg.python.org/에서 Mercurial 저장소를 사용할 수 있습니다.

3.2 버전 출시 이후, 주 저장소로 Mercurial을 채택할 계획이 있습니다. 이 분산 버전 관리 시스템은 커뮤니티 구성원들이 외부 변경 세트를 생성하고 공유하는 것을 더 쉽게 만들어 줄 것입니다. 자세한 내용은 PEP 385 를 참조하십시오.

새로운 버전 관리 시스템 사용법을 배우려면 Quick Start 또는 Guide to Mercurial Workflows 를 참조하십시오.

빌드 및 C API 변경 사항

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

  • idle, pydoc2to3 스크립트는 이제 make altinstall 시 버전별 접미사와 함께 설치됩니다 (bpo-10679).

  • Unicode 데이터베이스에 액세스하는 C 함수는 이제 narrow 유니코드 빌드에서도 전체 유니코드 범위의 문자를 수용하고 반환합니다 (Py_UNICODE_TOLOWER, Py_UNICODE_ISDECIMAL 등). 파이썬에서 눈에 띄는 차이점은 unicodedata.numeric() 이 이제 큰 코드 포인트에 대해 올바른 값을 반환하며, repr() 이 더 많은 문자를 출력 가능한 것으로 간주할 수 있다는 점입니다.

    (Bupjoe Lee가 보고하고 Amaury Forgeot D’Arc가 수정했습니다; bpo-5127.)

  • Computed gotos는 이제 지원되는 컴파일러(구성 스크립트에 의해 감지됨)에서 기본으로 활성화됩니다. --without-computed-gotos 를 지정하여 선택적으로 비활성화할 수도 있습니다.

    (Antoine Pitrou가 기여했습니다; bpo-9203.)

  • --with-wctype-functions 옵션이 제거되었습니다. 이제 모든 함수에 내장된 유니코드 데이터베이스가 사용됩니다.

    (Amaury Forgeot D’Arc가 기여했습니다; bpo-9210.)

  • 해시 값은 이제 포인터와 동일한 크기로 정의된 새로운 타입인 Py_hash_t 의 값을 가집니다. 이전에는 long 타입이었으며, 일부 64비트 운영체제에서는 여전히 32비트 길이였습니다. 이 수정의 결과로, 64비트 포인터를 사용하는 빌드에서 setdict 가 이제 2**32 개 이상의 항목을 보유할 수 있습니다(이전에는 해당 크기까지 확장될 수는 있었으나 성능이 급격히 저하되었습니다).

    (Raymond Hetinger가 제안하고 Benjamin Peterson이 구현했습니다; bpo-9778.)

  • 새로운 매크로 Py_VA_COPY`가 가변 인자 목록의 상태를 복사합니다. 이는 C99 *va_copy*와 동일하지만 모든 파이썬 플랫폼에서 사용할 있습니다 (:issue:`2443).

  • 새로운 C API 함수인 PySys_SetArgvEx() 를 통해 임베디드 인터프리터가 sys.path 를 수정하지 않고 sys.argv 를 설정할 수 있습니다 (bpo-5753).

  • PyEval_CallObject`은 이제 매크로 형태만 제공됩니다. 하위 호환성을 위해 유지되던 함수 선언이 제거되었습니다. 매크로는 1997년에 도입되었습니다 (:issue:`8276()).

  • PyLong_AsLongAndOverflow() 와 유사한 새로운 함수 PyLong_AsLongLongAndOverflow() 가 추가되었습니다. 두 함수 모두 파이썬 int 를 네이티브 고정 너비 타입으로 변환하면서 변환이 가능한 범위 내에 있는지 확인하는 기능을 제공합니다 (bpo-7767).

  • PyUnicode_CompareWithASCIIString() 함수는 이제 파이썬 문자열이 NUL 로 종료되는 경우 같지 않음(not equal) 을 반환합니다.

  • PyErr_NewException() 과 유사하지만 독스트링을 지정할 수 있는 새로운 함수 PyErr_NewExceptionWithDoc() 가 추가되었습니다. 이를 통해 C 예외도 순수 파이썬 예외와 동일한 자체 문서화 기능을 갖출 수 있습니다 (bpo-7033).

  • --with-valgrind 옵션과 함께 컴파일할 경우, Valgrind 환경에서 실행될 때 pymalloc 할당자가 자동으로 비활성화됩니다. 이를 통해 다른 경우에는 pymalloc의 이점을 누리면서 Valgrind 사용 시에는 개선된 메모리 누수 감지 성능을 얻을 수 있습니다 (bpo-2422).

  • PyArg_Parse 함수에서 O? 형식을 제거했습니다. 이 형식은 더 이상 사용되지 않으며 문서화된 적도 없습니다 (bpo-8837).

C-API에 몇 가지 다른 소규모 변경 사항이 있습니다. 전체 목록은 Misc/NEWS 파일을 참조하십시오.

또한, Mac OS X 빌드에 다수의 업데이트가 있었으며 자세한 내용은 Mac/BuildScript/README.txt 를 참조하십시오. 32/64비트 빌드를 실행하는 사용자의 경우 Mac OS X 10.6의 기본 Tcl/Tk에 알려진 문제가 있습니다. 따라서 ActiveState Tcl/Tk 8.5.9 와 같은 최신 대안을 설치할 것을 권장합니다. 자세한 내용은 https://www.python.org/download/mac/tcltk/를 참조하십시오.

Python 3.2로 이식

이 섹션에서는 앞서 설명한 변경 사항과 코드 수정이 필요할 수 있는 기타 버그 수정을 나열합니다.

  • configparser 모듈이 여러 차례 정리되었습니다. 주요 변경 사항은 기존의 ConfigParser 클래스를 오랫동안 권장되어 온 대체재인 SafeConfigParser 로 교체하는 것입니다. 또한 다음과 같은 소규모 비호환성이 있습니다:

    • get()set() 작업 시 이제 보간 구문이 검증됩니다. 기본 보간 방식에서 퍼센트 기호가 포함된 유효한 토큰은 %(name)s%% (이스케이프된 퍼센트 기호) 두 가지뿐입니다.

    • set()add_section() 메서드는 이제 값이 실제 문자열인지 확인합니다. 이전에는 지원되지 않는 유형이 의도치 않게 포함될 수 있었습니다.

    • 단일 소스로부터 가져온 중복된 섹션이나 옵션은 이제 DuplicateSectionError 또는 DuplicateOptionError 예외를 발생시킵니다. 이전에는 중복 항목이 이전 항목을 조용히 덮어썼습니다.

    • 인라인 주석이 기본적으로 비활성화되어 이제 값에 ; 문자를 안전하게 사용할 수 있습니다.

    • 이제 주석에 들여쓰기가 가능합니다. 결과적으로 멀티라인 값에서 줄 시작 부분에 ; 또는 # 이 나타나게 하려면 보간되어야 합니다. 이를 통해 값 내의 주석 접두 문자가 주석으로 오인되는 것을 방지합니다.

    • "" 는 이제 유효한 값이며 더 이상 자동으로 빈 문자열로 변환되지 않습니다. 빈 문자열을 사용하려면 한 줄에 "option =" 를 사용하십시오.

  • nntplib 모듈이 광범위하게 재작업되어 해당 API가 3.1 API와 호환되지 않는 경우가 많습니다.

  • bytearray 객체는 더 이상 파일 이름으로 사용할 수 없습니다. 대신 bytes 로 변환해야 합니다.

  • array.tostring()array.fromstring() 이 명확성을 위해 각각 array.tobytes()array.frombytes() 로 이름이 변경되었습니다. 이전 이름은 더 이상 사용되지 않습니다(Deprecated). (bpo-8990 참조.)

  • PyArg_Parse*() 함수:

    • “t#” 형식이 제거되었습니다. 대신 “s#” 또는 “s*”를 사용하십시오.

    • “w” 및 “w#” 형식이 제거되었습니다. 대신 “w*”를 사용하십시오.

  • 3.1에서 폐지된 PyCObject 타입이 제거되었습니다. 불투명한(opaque) C 포인터를 파이썬 객체로 래핑하려면 대신 PyCapsule API를 사용해야 합니다. 새 타입은 유형 안전성 정보를 전달하기 위한 잘 정의된 인터페이스와 데스트럭터를 호출하기 위한 덜 복잡한 시그니처를 갖습니다.

  • sys.setfilesystemencoding() 함수는 설계상의 결함으로 인해 제거되었습니다.

  • random.seed() 함수 및 메서드는 이제 문자열 시드에 sha512 해시 함수를 사용하여 솔트(salt)를 추가합니다. Python 3.1 시퀀스를 재현하기 위해 이전 버전의 seed 에 접근하려면 version 인자를 1 로 설정하십시오. random.seed(s, version=1).

  • 이전에 폐지된 string.maketrans() 함수가 제거되고 대신 정적 메서드인 bytes.maketrans()bytearray.maketrans() 를 사용합니다. 이 변경을 통해 string 모듈에서 어떤 유형이 지원되는지에 대한 혼란이 해결되었습니다. 이제 str, bytes, bytearray 는 각각 적절한 타입의 중간 변환 테이블을 갖는 고유의 maketranstranslate 메서드를 가집니다.

    (Georg Brandl이 기여했습니다; bpo-5675.)

  • 이전에 폐지된 contextlib.nested() 함수가 제거되고 대신 여러 컨텍스트 매니저를 수용할 수 있는 일반적인 with 문을 사용합니다. 후자의 기법은(내장 기능이므로) 더 빠르며, 하나가 예외를 발생시킬 때 여러 컨텍스트 매니저를 종료하는 처리가 더 효과적입니다.

    with open('mylog.txt') as infile, open('a.out', 'w') as outfile:
        for line in infile:
            if '<critical>' in line:
                outfile.write(line)
    

    (Georg Brandl과 Mattias Brändström이 기여했습니다; appspot issue 53094.)

  • struct.pack`은 이제 ``s`() 문자열 팩 코드를 위해 byte만 허용합니다. 이전에는 텍스트 인수를 허용하고 이를 UTF-8을 사용하여 암시적으로 byte로 인코딩했습니다. 이는 올바른 인코딩에 대한 가정을 포함하며, 고정 길이 구조의 섹션에 쓸 때 변동 길이 인코딩이 실패할 수 있다는 문제점이 있었기 때문입니다.

    struct.pack('<6sHHBBB', 'GIF87a', x, y) 와 같은 코드는 텍스트 대신 byte를 사용하도록 struct.pack('<6sHHBBB', b'GIF87a', x, y) 로 다시 작성해야 합니다.

    (David Beazley가 발견하고 Victor Stinner가 수정했습니다; bpo-10783.)

  • xml.etree.ElementTree 클래스는 이제 파싱에 실패할 때 xml.etree.ElementTree.ParseError 를 발생시킵니다. 이전에는 xml.parsers.expat.ExpatError 가 발생했습니다.

  • 부동 소수점에 대한 새롭고 더 긴 str() 값은 기존 출력 형식을 기반으로 하는 doctest를 깨뜨릴 수 있습니다.

  • subprocess.Popen 에서 close_fds 의 기본값은 Unix 환경에서 이제 True 입니다. Windows에서는 세 개의 표준 스트림이 None 으로 설정된 경우 True, 그렇지 않으면 False 입니다. 이전에는 close_fds 가 항상 기본적으로 False 였으며, 이로 인해 열린 파일 기술자(file descriptor)가 자식 프로세스로 유출될 때 해결하기 어려운 버그나 경쟁 상태가 발생하곤 했습니다.

  • urllib.requesthttp.client 에서 레거시 HTTP 0.9 지원이 제거되었습니다. 해당 기능은 여전히 서버 측(http.server)에 남아 있습니다.

    (Antoine Pitrou가 기여했습니다; bpo-10711.)

  • 타임아웃 모드인 SSL 소켓은 이제 타임아웃이 발생하면 일반적인 SSLError 대신 socket.timeout 을 발생시킵니다.

    (Antoine Pitrou가 기여했습니다; bpo-10272.)

  • 오해의 소지가 있는 기능인 PyEval_AcquireLock()PyEval_ReleaseLock() 이 공식적으로 폐지되었습니다. 대신 스레드 상태를 인식하는 API(예: PyEval_SaveThread()PyEval_RestoreThread())를 사용해야 합니다.

  • 보안 위험으로 인해 asyncore.handle_accept`이 폐지되었으며, 이를 대체하기 위해 새로운 기능인 :func:()!asyncore.handle_accepted`가 추가되었습니다.

    (Giampaolo Rodola가 기여했습니다; bpo-6706.)

  • 새로운 GIL 구현으로 인해 이제 PyEval_InitThreads()Py_Initialize() 전에 호출할 수 없습니다.

분실물 보관소