Що нового в Python 3.2

Автор:

Raymond Hettinger

This article explains the new features in Python 3.2 as compared to 3.1. Python 3.2 was released on February 20, 2011. It focuses on a few highlights and gives a few examples. For full details, see the Misc/NEWS file.

Дивись також

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

PEP, написаний Мартіном фон Льовісом.

PEP 389: Модуль аналізу командного рядка Argparse

Новий модуль для синтаксичного аналізу командного рядка, argparse, було представлено, щоб подолати обмеження optparse, які не забезпечували підтримку позиційних аргументів (не лише параметрів), підкоманд, необхідних параметрів та інших поширених шаблонів визначення та перевірки параметрів.

Цей модуль уже мав широкий успіх у спільноті як сторонній модуль. Оскільки модуль argparse є більш повнофункціональним, ніж його попередник, він тепер є кращим модулем для обробки командного рядка. Старіший модуль все ще залишається доступним через значну кількість застарілого коду, який залежить від нього.

Ось анотований приклад синтаксичного аналізатора, який показує такі функції, як обмеження результатів набором варіантів, визначення metavar на екрані довідки, перевірка наявності одного чи кількох позиційних аргументів і створення необхідної опції:

import argparse
parser = argparse.ArgumentParser(
            description = 'Manage servers',         # main description for help
            epilog = 'Tested on Solaris and Linux') # displayed after help
parser.add_argument('action',                       # argument name
            choices = ['deploy', 'start', 'stop'],  # three allowed values
            help = 'action on each target')         # help msg
parser.add_argument('targets',
            metavar = 'HOSTNAME',                   # var name used in help msg
            nargs = '+',                            # require one or more targets
            help = 'url for target machines')       # help msg explanation
parser.add_argument('-u', '--user',                 # -u or --user option
            required = True,                        # make it a required argument
            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')   # first subgroup
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',        # second subgroup
                                 aliases=('steer', 'turn'))         # equivalent names
parser_m.add_argument('-c', '--course', type=int, required=True)
parser_m.add_argument('-s', '--speed', type=int, default=0)
$ ./helm.py --help                         # top level help (launch and move)
$ ./helm.py launch --help                  # help for launch options
$ ./helm.py launch --missiles              # set missiles=True and torpedos=False
$ ./helm.py steer --course 180 --speed 5   # set movement parameters

Дивись також

PEP 389 - Новий модуль аналізу командного рядка

PEP, написаний Стівеном Бетардом.

Оновлення коду optparse для детальної інформації про відмінності від optparse.

PEP 391: Конфігурація на основі словника для журналювання

The logging module provided two kinds of configuration, one style with function calls for each option or another style driven by an external file saved in a configparser format. Those options did not provide the flexibility to create configurations from JSON or YAML files, nor did they support incremental configuration, which is needed for specifying logger options from a command line.

Щоб підтримувати більш гнучкий стиль, модуль тепер пропонує logging.config.dictConfig() для визначення конфігурації журналювання за допомогою простих словників Python. Опції конфігурації включають засоби форматування, обробники, фільтри та реєстратори. Ось робочий приклад словника конфігурації:

{"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 - Конфігурація для журналювання на основі словника

PEP, написаний Вінаєм Саджипом.

PEP 3148: модуль concurrent.futures

Код для створення паралелізму та керування ним збирається в новому просторі імен верхнього рівня concurrent. Його першим членом є пакет futures, який забезпечує єдиний інтерфейс високого рівня для керування потоками та процесами.

Дизайн для concurrent.futures був натхненний пакетом java.util.concurrent. У цій моделі запущений виклик і його результат представлені об’єктом Future, який абстрагує функції, спільні для потоків, процесів і віддалених викликів процедур. Цей об’єкт підтримує перевірки статусу (запущено або виконано), тайм-аути, скасування, додавання зворотних викликів і доступ до результатів або винятків.

Основною пропозицією нового модуля є пара класів виконавців для запуску викликів і керування ними. Мета виконавців — спростити використання існуючих інструментів для здійснення паралельних викликів. Вони економлять зусилля, необхідні для налаштування пулу ресурсів, запуску викликів, створення черги результатів, додавання обробки тайм-ауту та обмеження загальної кількості потоків, процесів або віддалених викликів процедур.

В ідеалі кожна програма має спільно використовувати одного виконавця для кількох компонентів, щоб можна було централізовано керувати обмеженнями процесів і потоків. Це вирішує проблему проектування, яка виникає, коли кожен компонент має власну конкуруючу стратегію управління ресурсами.

Обидва класи мають спільний інтерфейс із трьома методами: submit() для планування виклику та повернення об’єкта Future; map() для планування багатьох асинхронних викликів одночасно та shutdown() для звільнення ресурсів. Цей клас є context manager і може використовуватися в операторі with, щоб гарантувати автоматичне звільнення ресурсів після завершення виконання незавершених ф’ючерсів.

Простий приклад ThreadPoolExecutor — це запуск чотирьох паралельних потоків для копіювання файлів:

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 - Ф’ючерси - асинхронне виконання обчислень

PEP, написаний Браяном Квінланом.

Код для потокової паралельної URL-адреси читає, приклад використання потоків для отримання кількох веб-сторінок паралельно.

Код для паралельного обчислення простих чисел, приклад, що демонструє ProcessPoolExecutor.

PEP 3147: Каталоги сховищ PYC

Схема Python для кешування байт-коду у файлах .pyc погано працювала в середовищах із кількома інтерпретаторами Python. Якщо один інтерпретатор зустріне кешований файл, створений іншим інтерпретатором, він перекомпілює джерело та перезапише кешований файл, таким чином втрачаючи переваги кешування.

Питання «бій pyc» стало більш помітним, оскільки дистрибутиви Linux стали звичайними для доставки з декількома версіями Python. Ці конфлікти також виникають з альтернативами CPython, такими як Unladen Swallow.

Щоб вирішити цю проблему, механізм імпорту Python було розширено для використання різних імен файлів для кожного інтерпретатора. Замість того, щоб 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'
    
  • The tag that is unique to each interpreter is accessible from the imp module:

    >>> import imp 
    >>> imp.get_tag() 
    'cpython-32'
    
  • Scripts that try to deduce source filename from the imported file now need to be smarter. It is no longer sufficient to simply strip the «c» from a «.pyc» filename. Instead, use the new functions in the imp module:

    >>> 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'
    
  • Модулі py_compile і compileall оновлено, щоб відобразити нову угоду про іменування та цільовий каталог. Виклик compileall у командному рядку має нові параметри: -i для вказівки списку файлів і каталогів для компіляції та -b, який змушує файли байт-коду записуватися в їх старе розташування, а не в __pycache__.

  • The importlib.abc module has been updated with new abstract base classes for loading bytecode files. The obsolete ABCs, PyLoader and PyPycLoader, have been deprecated (instructions on how to stay Python 3.1 compatible are included with the documentation).

Дивись також

PEP 3147 - Каталоги репозиторіїв PYC

PEP, автор Баррі Варшау.

PEP 3149: файли .so з тегами версії ABI

Каталог сховища PYC дозволяє одночасно розміщувати кілька файлів кешу байт-кодів. Цей PEP реалізує подібний механізм для файлів спільних об’єктів, надаючи їм загальний каталог і окремі імена для кожної версії.

Загальний каталог є «pyshared», а назви файлів відрізняються ідентифікацією реалізації Python (наприклад, CPython, PyPy, Jython тощо), номерами основної та другорядної версій і необов’язковими прапорцями збірки (наприклад, «d» для debug, «m» для pymalloc, «u» для широкого юнікоду). Для довільного пакета «foo» ви можете побачити ці файли, коли встановлено дистрибутивний пакет:

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

У самому Python теги доступні з функцій у модулі sysconfig:

>>> import sysconfig
>>> sysconfig.get_config_var('SOABI')       # find the version tag
'cpython-32mu'
>>> sysconfig.get_config_var('EXT_SUFFIX')  # find the full filename extension
'.cpython-32mu.so'

Дивись також

PEP 3149 - файли .so з тегами версії ABI

PEP, автор Баррі Варшау.

PEP 3333: Інтерфейс шлюзу веб-сервера Python v1.0.1

Цей інформаційний PEP пояснює, як протокол WSGI має обробляти проблеми з байтами/текстом. Проблема полягає в тому, що обробку рядків у Python 3 найзручніше обробляти за допомогою типу str, хоча сам протокол HTTP орієнтований на байти.

PEP розрізняє так звані власні рядки, які використовуються для заголовків запитів/відповідей і метаданих, від байтових рядків, які використовуються для тіл запитів і відповідей.

The native strings are always of type str but are restricted to code points between U+0000 through U+00FF which are translatable to bytes using Latin-1 encoding. These strings are used for the keys and values in the environment dictionary and for response headers and statuses in the start_response() function. They must follow RFC 2616 with respect to encoding. That is, they must either be ISO-8859-1 characters or use RFC 2047 MIME encoding.

Для розробників, які портують програми WSGI з Python 2, ось основні моменти:

  • Якщо програма вже використовувала рядки для заголовків у Python 2, змінювати не потрібно.

  • Якщо замість цього програма закодувала вихідні заголовки або декодувала вхідні заголовки, тоді заголовки потрібно буде повторно закодувати в Latin-1. Наприклад, вихідний заголовок, закодований у utf-8, використовував h.encode('utf-8'), тепер потребує конвертації з байтів у власні рядки за допомогою h.encode('utf-8'). decode('latin-1').

  • Values yielded by an application or sent using the write() method must be byte strings. The start_response() function and environ must use native strings. The two cannot be mixed.

For server implementers writing CGI-to-WSGI pathways or other CGI-style protocols, the users must to be able access the environment using native strings even though the underlying platform may have a different convention. To bridge this gap, the wsgiref module has a new function, wsgiref.handlers.read_environ() for transcoding CGI variables from os.environ into native strings and returning a new dictionary.

Дивись також

PEP 3333 - Інтерфейс шлюзу веб-сервера Python v1.0.1

PEP, написаний Філіпом Ебі.

Інші зміни мови

Деякі менші зміни, внесені до основної мови Python:

  • Форматування рядка для format() і str.format() отримало нові можливості для символу форматування #. Раніше для цілих чисел у двійковій, вісімковій чи шістнадцятковій системі виводу ставився префікс «0b», «0o» або «0x» відповідно. Тепер він також може обробляти числа з плаваючою точкою, комплексні та десяткові числа, завдяки чому вивід завжди матиме десяткову крапку, навіть якщо за нею не йде жодна цифра.

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

    (Запропоновано Марком Дікінсоном і реалізовано Еріком Смітом у bpo-7094.)

  • Існує також новий метод str.format_map(), який розширює можливості існуючого методу str.format(), приймаючи довільні об’єкти mapping. Цей новий метод дає змогу використовувати форматування рядка з будь-яким із багатьох словникових об’єктів Python, таких як defaultdict, Shelf, ConfigParser , або dbm. Це також корисно з власними підкласами dict, які нормалізують ключі перед пошуком або надають метод __missing__() для невідомих ключів:

    >>> 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.)

  • The interpreter can now be started with a quiet option, -q, to prevent the copyright and version information from being displayed in the interactive mode. The option can be introspected using the sys.flags attribute:

    $ 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)
    

    (Надав Марчін Войдир у 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
    

    (Виявлено Юрієм Селівановим і виправлено Бенджаміном Петерсоном; bpo-9666.)

  • str() числа з плаваючою точкою або комплексного числа тепер збігається з його repr(). Раніше форма str() була коротшою, але це лише викликало плутанину, і тепер вона більше не потрібна, оскільки найкоротша можлива repr() відображається за замовчуванням:

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

    (Запропоновано та реалізовано Марком Дікінсоном; bpo-9337.)

  • Об’єкти memoryview тепер мають метод release() і тепер вони також підтримують протокол керування контекстом. Це дозволяє своєчасно звільнити будь-які ресурси, отримані під час запиту буфера з вихідного об’єкта.

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

    (Додав Антуан Пітру; bpo-9757.)

  • Раніше було заборонено видаляти ім’я з локального простору імен, якщо воно зустрічається як вільна змінна у вкладеному блоці:

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

    Тепер це дозволено. Пам’ятайте, що ціль речення except очищено, тому цей код, який раніше працював з Python 2.6, викликав SyntaxError з Python 3.1 і тепер знову працює:

    def f():
        def print_error():
            print(e)
        try:
            something
        except Exception as e:
            print_error()
            # implicit "del e" here
    

    (Див. bpo-4617.)

  • Struct sequence types are now subclasses of tuple. This means that C structures like those returned by os.stat(), time.gmtime(), and sys.version_info now work like a named tuple and now work with functions and methods that expect a tuple as an argument. This is a big step forward in making the C structures as flexible as their pure Python counterparts:

    >>> 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 і реалізовано Бенджаміном Петерсоном у bpo-8413.)

  • Тепер попередженнями легше керувати за допомогою змінної середовища PYTHONWARNINGS як альтернативи використанню -W у командному рядку:

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

    (Запропоновано Barry Warsaw і реалізовано Philip Jenvey у bpo-7301.)

  • Додано нову категорію попереджень ResourceWarning. Випускається, коли виявляються потенційні проблеми із споживанням ресурсів або очищенням. За замовчуванням у звичайних збірках випуску його вимкнено, але його можна ввімкнути за допомогою засобів, наданих модулем warnings, або в командному рядку.

    A ResourceWarning is issued at interpreter shutdown if the gc.garbage list isn’t empty, and if gc.DEBUG_UNCOLLECTABLE is set, all uncollectable objects are printed. This is meant to make the programmer aware that their code contains object finalization issues.

    ResourceWarning також видається, коли file object знищується без явного закриття. Хоча засіб звільнення для такого об’єкта гарантує, що він закриває основний ресурс операційної системи (зазвичай, дескриптор файлу), затримка звільнення об’єкта може спричинити різні проблеми, особливо під Windows. Ось приклад увімкнення попередження з командного рядка:

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

    (Додано Антуаном Пітру та Георгом Брандлом у bpo-10093 та bpo-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)
    

    (Надано Даніелем Штуцбахом у bpo-9213, Олександром Бєлопольським у bpo-2690 та Ніком Когланом у bpo-10889.)

  • Вбудовану функцію callable() з Py2.x було відроджено. Він надає стислу, зрозумілу альтернативу використанню abstract base class у виразі на зразок isinstance(x, collections.Callable):

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

    (Див. bpo-10518.)

  • Механізм імпорту Python тепер може завантажувати модулі, встановлені в каталогах із символами, відмінними від ASCII, у імені шляху. Це вирішило серйозну проблему з домашніми каталогами для користувачів із символами, відмінними від ASCII, у їхніх іменах користувачів.

(Потрібна велика робота Віктора Стіннера в bpo-9425.)

Нові, покращені та застарілі модулі

Стандартна бібліотека Python зазнала значних зусиль з обслуговування та покращення якості.

Найбільшою новиною для Python 3.2 є те, що пакет email, модуль mailbox і модулі nntplib тепер коректно працюють із моделлю байт/текст у Python 3. Вперше , існує правильна обробка повідомлень із змішаним кодуванням.

У стандартній бібліотеці більше уваги приділялося кодуванням і питанням тексту та байтів. Зокрема, під час взаємодії з операційною системою тепер краще обмінюватися даними, відмінними від ASCII, за допомогою кодування Windows MBCS, кодування з урахуванням локалі або UTF-8.

Ще однією важливою перевагою є додавання значно кращої підтримки з’єднань SSL і сертифікатів безпеки.

Крім того, більше класів тепер реалізують context manager для підтримки зручного та надійного очищення ресурсів за допомогою оператора with.

електронною поштою

Зручність використання пакета email у Python 3 була здебільшого виправлена завдяки значним зусиллям Р. Девіда Мюррея. Проблема полягала в тому, що електронні листи зазвичай читаються та зберігаються у формі bytes, а не str тексту, і вони можуть містити кілька кодувань в одному електронному листі. Отже, пакет електронної пошти потрібно було розширити для аналізу та генерації повідомлень електронної пошти у форматі байтів.

  • Нові функції message_from_bytes() і message_from_binary_file(), а також нові класи BytesFeedParser і BytesParser дозволяють двійковий код дані повідомлення, які потрібно розібрати в об’єкти моделі.

  • З урахуванням байтів, введених у модель, get_payload() за замовчуванням декодує тіло повідомлення, яке має Content-Transfer-Encoding 8bit, використовуючи набір символів, указаний у заголовки MIME та повертає результуючий рядок.

  • Враховуючи байти, введені в модель, Generator перетворить тіла повідомлень, які мають Content-Transfer-Encoding 8bit, на 7bit Content-Transfer-Encoding.

    Заголовки з незакодованими не-ASCII байтами вважаються RFC 2047-кодованими з використанням набору символів unknown-8bit.

  • Новий клас BytesGenerator створює байти як вихідні дані, зберігаючи будь-які незмінені дані, що не належать до ASCII, які були присутні у вхідних даних, використаних для побудови моделі, включаючи тіла повідомлень із Content-Transfer-Encoding з 8bit.

  • Клас smtplib SMTP тепер приймає рядок байтів для аргументу msg для методу sendmail() і новий метод send_message() приймає об’єкт Message і за бажанням може отримати адреси from_addr і to_addrs безпосередньо з об’єкта.

(Запропоновано та реалізовано Р. Девідом Мюрреєм, bpo-4661 і bpo-10321.)

дерево елементів

The xml.etree.ElementTree package and its xml.etree.cElementTree counterpart have been updated to version 1.3.

Додано кілька нових корисних функцій і методів:

Два методи застаріли:

  • xml.etree.ElementTree.getchildren() use list(elem) instead.

  • xml.etree.ElementTree.getiterator() use Element.iter instead.

Докладні відомості про оновлення див. у розділі 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)
    

    Якщо таблиця списку телефонів оновлюється, застарілий вміст кешу можна очистити за допомогою:

    >>> get_phone_number.cache_clear()
    

    (Contributed by Raymond Hettinger and incorporating design ideas from Jim Baker, Miki Tebeka, and Nick Coghlan; see recipe 498245, recipe 577479, bpo-10586, and bpo-10593.)

  • The functools.wraps() decorator now adds a __wrapped__ attribute pointing to the original callable function. This allows wrapped functions to be introspected. It also copies __annotations__ if defined. And now it also gracefully skips over missing attributes such as __doc__ which might not be defined for the wrapped callable.

    У наведеному вище прикладі кеш можна видалити, відновивши вихідну функцію:

    >>> get_phone_number = get_phone_number.__wrapped__    # uncached function
    

    (Автори Нік Коглан і Терренс Коул; bpo-9567, bpo-3445 і bpo-8814.)

  • Щоб допомогти писати класи з розширеними методами порівняння, новий декоратор functools.total_ordering() використовуватиме існуючі методи рівності та нерівності для заповнення решти методів.

    Наприклад, введення __eq__ і __lt__ дозволить 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 решта методів порівняння заповнюється автоматично.

    (Надав Реймонд Геттінгер.)

  • Щоб допомогти у перенесенні програм із Python 2, функція functools.cmp_to_key() перетворює стару функцію порівняння на сучасну key function:

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

    Приклади сортування та короткий посібник із сортування див. у посібнику Sorting HowTo.

    (Надав Реймонд Геттінгер.)

itertools

  • Модуль itertools має нову функцію accumulate(), створену на основі оператора scan APL і функції accumulate Numpy:

    >>> 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() див. приклади для випадкового модуля.

    (Надано Реймондом Геттінгером і враховано пропозиції щодо дизайну Марка Дікінсона.)

колекції

  • Клас 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})
    

    (Надав Реймонд Геттінгер.)

  • Клас collections.OrderedDict має новий метод move_to_end(), який бере наявний ключ і переміщує його на першу чи останню позицію в упорядкованій послідовності.

    За замовчуванням елемент переміщується на останню позицію. Це еквівалентно оновленню запису за допомогою 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']
    

    (Надав Реймонд Геттінгер.)

  • У класі 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'])
    

    (Надав Реймонд Геттінгер.)

різьблення

Модуль threading має новий клас синхронізації Barrier для того, щоб кілька потоків чекали, поки всі вони досягнуть спільної точки перешкоди. Бар’єри корисні для забезпечення того, щоб завдання з кількома попередніми умовами не запускалося, доки не будуть виконані всі завдання-попередники.

Бар’єри можуть працювати з довільною кількістю потоків. Це узагальнення Rendezvous, яке визначено лише для двох потоків.

Реалізовані як двофазний циклічний бар’єр, об’єкти Barrier підходять для використання в циклах. Окремі фази заповнення та виливання гарантують, що всі потоки будуть звільнені (осушені) до того, як будь-який з них зможе повернутися назад і знову увійти в бар’єр. Після кожного циклу бар’єр повністю скидається.

Приклад використання бар’єрів:

from threading import Barrier, Thread

def get_votes(site):
    ballots = conduct_election(site)
    all_polls_closed.wait()        # do not count until all polls are closed
    totals = summarize(ballots)
    publish(site, totals)

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

У цьому прикладі бар’єр забезпечує виконання правила, згідно з яким голоси не можуть бути підраховані на жодній виборчій дільниці, доки всі виборчі дільниці не будуть закриті. Зверніть увагу, що рішення з бар’єром схоже на рішення з threading.Thread.join(), але потоки залишаються живими та продовжують виконувати роботу (підсумовуючи бюлетені) після перетину точки бар’єру.

Якщо будь-яке з попередніх завдань може зависати або відкладатися, можна створити бар’єр за допомогою додаткового параметра 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)

У цьому прикладі бар’єр забезпечує більш надійне правило. Якщо деякі виборчі дільниці не закінчуються до опівночі, шлагбаум закінчується, а бюлетені запечатуються та залишаються в черзі для подальшої обробки.

See Barrier Synchronization Patterns for more examples of how barriers can be used in parallel computing. Also, there is a simple but thorough explanation of barriers in The Little Book of Semaphores, section 3.6.

(Надав Крістіян Валур Йонссон із оглядом API Джеффрі Яскіним у bpo-8777.)

дата, час і час

  • Модуль datetime має новий тип timezone, який реалізує інтерфейс tzinfo шляхом повернення фіксованого зміщення UTC і назви часового поясу. Це полегшує створення об’єктів datetime з урахуванням часового поясу:

    >>> from datetime import datetime, timezone
    
    >>> datetime.now(timezone.utc)
    datetime.datetime(2010, 12, 8, 21, 4, 2, 923754, tzinfo=datetime.timezone.utc)
    
    >>> 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 і розділити на об’єкти float і int. І об’єкти timedelta тепер можуть розділяти один одного.

  • Метод datetime.date.strftime() більше не обмежується роками після 1900. Новий підтримуваний діапазон років становить від 1000 до 9999 включно.

  • Whenever a two-digit year is used in a time tuple, the interpretation has been governed by time.accept2dyear. The default is True which means that for a two-digit year, the century is guessed according to the POSIX rules governing the %y strptime format.

    Starting with Py3.2, use of the century guessing heuristic will emit a DeprecationWarning. Instead, it is recommended that time.accept2dyear be set to False so that large date ranges can be used without guesswork:

    >>> import time, warnings
    >>> warnings.resetwarnings()      # remove the default warning filters
    
    >>> time.accept2dyear = True      # guess whether 11 means 11 or 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     # use the full range of allowable dates
    >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0))
    'Fri Jan  1 12:34:56 11'
    

    Several functions now have significantly expanded date ranges. When time.accept2dyear is false, the time.asctime() function will accept any year that fits in a C int, while the time.mktime() and time.strftime() functions will accept the full range supported by the corresponding operating system functions.

(Надано Олександром Бєлопольським та Віктором Стіннером у bpo-1289118, bpo-5094, bpo-6641, bpo-2706, bpo-1777412, bpo-8013 і bpo-10827.)

математика

Модуль math було оновлено шістьма новими функціями, натхненними стандартом C99.

Функція isfinite() забезпечує надійний і швидкий спосіб визначення спеціальних значень. Він повертає True для звичайних чисел і False для Nan або Infinity:

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

Функція expm1() обчислює e**x-1 для малих значень x без втрати точності, яка зазвичай супроводжує віднімання майже рівних величин:

>>> 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))   # portion of normal distribution within 1 standard deviation
0.682689492137086
>>> erfc(1.0/sqrt(2.0))  # portion of normal distribution outside 1 standard deviation
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

(Надав Марк Дікінсон.)

абв

Модуль abc тепер підтримує abstractclassmethod() і abstractstaticmethod().

Ці інструменти дають змогу визначити abstract base class, який потребує реалізації конкретного classmethod() або staticmethod():

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

(Патч надіслав Даніель Урбан; bpo-5867.)

io

io.BytesIO має новий метод, getbuffer(), який забезпечує функції, подібні до memoryview(). Він створює редагований вигляд даних без копіювання. Довільний доступ до буфера та підтримка нотації фрагментів добре підходять для редагування на місці:

>>> 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'

(Надав Антуан Пітру в bpo-5506.)

reprlib

When writing a __repr__() method for a custom container, it is easy to forget to handle the case where a member refers back to the container itself. Python’s builtin objects such as list and set handle self-reference by displaying «…» in the recursive part of the representation string.

To help write such __repr__() methods, the reprlib module has a new decorator, recursive_repr(), for detecting recursive calls to __repr__() and substituting a placeholder string instead:

>>> 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'>

(Надано Реймондом Геттінгером у bpo-9826 та bpo-9840.)

лісозаготівля

Окрім описаної вище конфігурації на основі словника, пакет logging має багато інших покращень.

Документацію з журналювання було доповнено основним підручником, розширеним підручникомі кулінарною книгою з рецептами журналювання. Ці документи є найшвидшим способом дізнатися про лісозаготівлю.

Функція налаштування logging.basicConfig() отримала аргумент style для підтримки трьох різних типів форматування рядків. За замовчуванням для традиційного форматування %-formatting встановлено значення «%», можна встановити значення «{» для нового стилю 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")

If no configuration is set-up before a logging event occurs, there is now a default configuration using a StreamHandler directed to sys.stderr for events of WARNING level or higher. Formerly, an event occurring before a configuration was set-up would either raise an exception or silently drop the event depending on the value of logging.raiseExceptions. The new default handler is stored in logging.lastResort.

Використання фільтрів спрощено. Замість створення об’єкта Filter предикатом може бути будь-який виклик Python, який повертає True або False.

З’явилася низка інших покращень, які додають гнучкості та спрощують налаштування. Перегляньте документацію модуля, щоб отримати повний список змін у Python 3.2.

csv

Модуль csv тепер підтримує новий діалект, unix_dialect, який застосовує лапки для всіх полів і традиційний стиль Unix із '\n' як символ закінчення рядка. Зареєстрована діалектна назва 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"

(Новий діалект, запропонований Джеєм Телботом у bpo-5975, і новий метод, запропонований Едом Абрахамом у bpo-1537721.)

contextlib

Існує новий і трохи приголомшливий інструмент ContextDecorator, який корисний для створення context manager, який виконує подвійну функцію як декоратор функції.

Для зручності ця нова функціональність використовується contextmanager(), тому не потрібно докладати додаткових зусиль для підтримки обох ролей.

Основна ідея полягає в тому, що як менеджери контексту, так і декоратори функцій можна використовувати для обгорток до і після дії. Менеджери контексту обгортають групу операторів за допомогою оператора with, а декоратори функцій обгортають групу операторів, укладених у функцію. Отже, іноді виникає потреба написати обгортку до або після дії, яку можна використовувати в обох ролях.

Наприклад, іноді корисно обернути функції або групи операторів за допомогою реєстратора, який може відстежувати час входу та час виходу. Замість того, щоб писати як декоратор функції, так і менеджер контексту для завдання, 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 повернути примірник журналювання для використання в тілі вкладених операторів.

(Надав Майкл Форд у bpo-9110.)

десятковий і дробовий

Марк Дікінсон розробив елегантну та ефективну схему, яка гарантує, що різні типи числових даних матимуть однакове хеш-значення, якщо їхні фактичні значення рівні (bpo-8188):

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

Some of the hashing details are exposed through a new attribute, sys.hash_info, which describes the bit width of the hash value, the prime modulus, the hash values for infinity and nan, and the multiplier used for the imaginary part of a number:

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

An early decision to limit the interoperability of various numeric types has been relaxed. It is still unsupported (and ill-advised) to have implicit mixing in arithmetic expressions such as Decimal('1.1') + float('1.1') because the latter loses information in the process of constructing the binary float. However, since existing floating point value can be converted losslessly to either a decimal or rational representation, it makes sense to add them to the constructor and to support mixed-type comparisons.

  • Конструктор decimal.Decimal тепер приймає об’єкти float безпосередньо, тому більше не потрібно використовувати метод from_float() (bpo-8257) .

  • Порівняння змішаних типів тепер повністю підтримуються, тому об’єкти Decimal можна безпосередньо порівнювати з float і fractions.Fraction (bpo-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)

Another useful change for the decimal module is that the Context.clamp attribute is now public. This is useful in creating contexts that correspond to the decimal interchange formats specified in IEEE 754 (see bpo-8540).

(Надано Марком Дікінсоном і Реймондом Геттінгером.)

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.mmap і fileinput.input() також розширили менеджери контексту автоматичного закриття:

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

(Надано Тареком Зіаде та Джампаоло Родола у bpo-4972 та Георгом Брандлом у bpo-8046 та bpo-1286.)

Клас FTP_TLS тепер приймає параметр context, який є об’єктом ssl.SSLContext, що дозволяє об’єднувати параметри конфігурації SSL, сертифікати та закриті ключі в єдиний (потенційно довготривалий) структура.

(Надав Джампаоло Родола; bpo-8806.)

відкрити

Функції os.popen() і subprocess.Popen() тепер підтримують оператори with для автоматичного закриття дескрипторів файлів.

(Надано Антуаном Пітру та Браяном Кертіном у bpo-7461 та bpo-10554.)

вибрати

The select module now exposes a new, constant attribute, PIPE_BUF, which gives the minimum number of bytes which are guaranteed not to block when select.select() says a pipe is ready for writing.

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

(Доступно в системах Unix. Патч Себастьєна Сабле в bpo-9862)

gzip і zipfile

gzip.GzipFile тепер реалізує io.BufferedIOBase abstract base class (крім truncate()). Він також має метод peek() і підтримує об’єкти файлів, які не можна шукати, а також об’єкти з нульовим доповненням.

Модуль gzip також отримує функції compress() і decompress() для полегшення стиснення та розпакування в пам’яті. Майте на увазі, що текст має бути закодований як bytes перед стисненням і розпакуванням:

>>> 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'

(Надано Анандом Б. Піллаєм у bpo-3488; і Антуаном Пітру, Ніром Ейдесом і Браяном Кертіном у bpo-9962, bpo-1675951, bpo-7471 та :issue: «2846».)

Also, the zipfile.ZipExtFile class was reworked internally to represent files stored inside an archive. The new implementation is significantly faster and can be wrapped in an io.BufferedReader object for more speedups. It also solves an issue where interleaved calls to read and readline gave the wrong results.

(Патч надіслано Nir Aides у bpo-7610.)

tarfile

Клас TarFile тепер можна використовувати як менеджер контексту. Крім того, його метод add() має новий параметр, filter, який контролює, які файли додаються до архіву, і дозволяє редагувати метадані файлу.

Новий параметр фільтр замінює старіший, менш гнучкий параметр exclude, який зараз є застарілим. Якщо вказано, необов’язковий параметр filter має бути аргументом ключового слова (keyword argument). Функція фільтра, надана користувачем, приймає об’єкт TarInfo і повертає оновлений об’єкт TarInfo, або якщо вона хоче, щоб файл було виключено, функція може повернути None:

>>> import tarfile, glob

>>> def myfilter(tarinfo):
...     if tarinfo.isfile():             # only save real files
...         tarinfo.uname = 'monty'      # redact the user name
...         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

(Запропоновано Тареком Зіаді та реалізовано Ларсом Густебелем у bpo-6856.)

хешліб

Модуль 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'}

(Запропоновано Карлом Чене в bpo-7418.)

аст

Модуль ast має чудовий інструмент загального призначення для безпечної оцінки рядків виразів за допомогою синтаксису літералів Python. Функція ast.literal_eval() служить безпечною альтернативою вбудованій функції eval(), якою легко зловживати. Python 3.2 додає літерали bytes і set до списку підтримуваних типів: рядки, байти, числа, кортежі, списки, dicts, набори, логічні значення та None.

>>> 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>

(Реалізовано Бенджаміном Петерсоном і Георгом Брандлом.)

ос

Різні операційні системи використовують різні кодування для імен файлів і змінних середовища. Модуль os надає дві нові функції, fsencode() і fsdecode(), для кодування та декодування імен файлів:

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

Some operating systems allow direct access to encoded bytes in the environment. If so, the os.supports_bytes_environ constant will be true.

Для прямого доступу до закодованих змінних середовища (якщо доступно) використовуйте нову функцію os.getenvb() або використовуйте os.environb, яка є байтовою версією os.environ.

(Надав Віктор Стіннер.)

шутил

Функція shutil.copytree() має дві нові опції:

  • ignore_dangling_symlinks: коли symlinks=False, щоб функція копіювала файл, на який вказує символічне посилання, а не саме символічне посилання. Цей параметр заглушить повідомлення про помилку, якщо файл не існує.

  • copy_function: це виклик, який використовуватиметься для копіювання файлів. shutil.copy2() використовується за умовчанням.

(Надав Тарек Зіаде.)

Крім того, модуль shutil тепер підтримує операції архівування для файлів zip, нестиснутих tar-файлів, tar-файлів gzip і tar-файлів bzip. Існують функції для реєстрації додаткових форматів архівних файлів (таких як стиснуті tar-файли xz або спеціальні формати).

Основними функціями є make_archive() і unpack_archive(). За замовчуванням обидва працюють з поточним каталогом (який можна встановити за допомогою os.chdir()) і будь-якими підкаталогами. Ім’я файлу архіву має бути вказано з повним шляхом. Етап архівування є неруйнівним (оригінальні файли залишаються без змін).

>>> import shutil, pprint

>>> os.chdir('mydata')  # change to the source directory
>>> f = shutil.make_archive('/var/backup/mydata',
...                         'zip')      # archive the current directory
>>> f                                   # show the name of archive
'/var/backup/mydata.zip'
>>> os.chdir('tmp')                     # change to an unpacking
>>> shutil.unpack_archive('/var/backup/mydata.zip')  # recover the data

>>> pprint.pprint(shutil.get_archive_formats())  # display known formats
[('bztar', "bzip2'ed tar-file"),
 ('gztar', "gzip'ed tar-file"),
 ('tar', 'uncompressed tar file'),
 ('zip', 'ZIP file')]

>>> shutil.register_archive_format(     # register a new archive format
...     name='xz',
...     function=xz.compress,           # callable archiving function
...     extra_args=[('level', 8)],      # arguments to the function
...     description='xz compression'
... )

(Надав Тарек Зіаде.)

sqlite3

Модуль sqlite3 оновлено до версії pysqlite 2.6.0. Він має дві нові можливості.

  • The sqlite3.Connection.in_transit attribute is true if there is an active transaction for uncommitted changes.

  • Методи sqlite3.Connection.enable_load_extension() і sqlite3.Connection.load_extension() дозволяють завантажувати розширення SQLite з файлів «.so». Одним із відомих розширень є розширення повнотекстового пошуку, що поширюється разом із SQLite.

(Надано Р. Девідом Мюрреєм і Шашватом Анандом; bpo-8845.)

html

Представлено новий модуль html лише з однією функцією, escape(), яка використовується для екранування зарезервованих символів із розмітки HTML:

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

гніздо

Модуль socket має два нових покращення.

  • Об’єкти Socket тепер мають метод detach(), який переводить сокет у закритий стан без фактичного закриття основного дескриптора файлу. Останній потім можна повторно використовувати для інших цілей. (Додав Антуан Пітру; bpo-8524.)

  • socket.create_connection() тепер підтримує протокол керування контекстом для безумовного використання винятків socket.error і закриття сокета після завершення. (Надав Джампаоло Родола; bpo-9794.)

ssl

Модуль ssl додав низку функцій, щоб задовольнити загальні вимоги до безпечних (зашифрованих, автентифікованих) інтернет-з’єднань:

  • Новий клас, SSLContext, служить контейнером для постійних даних SSL, таких як налаштування протоколу, сертифікати, приватні ключі та різні інші параметри. Він містить wrap_socket() для створення SSL-сокета з контексту SSL.

  • A new function, ssl.match_hostname(), supports server identity verification for higher-level protocols by implementing the rules of HTTPS (from RFC 2818) which are also suitable for other protocols.

  • The ssl.wrap_socket() constructor function now takes a ciphers argument. The ciphers string lists the allowed encryption algorithms using the format described in the OpenSSL documentation.

  • При зв’язуванні з останніми версіями OpenSSL модуль ssl тепер підтримує розширення індикації імені сервера для протоколу TLS, дозволяючи кільком «віртуальним хостам» використовувати різні сертифікати на одному IP-порту. Це розширення підтримується лише в режимі клієнта та активується шляхом передачі аргументу server_hostname до ssl.SSLContext.wrap_socket().

  • До модуля ssl додано різні параметри, наприклад OP_NO_SSLv2, який вимикає небезпечний і застарілий протокол SSLv2.

  • Розширення тепер завантажує всі шифри OpenSSL і алгоритми дайджесту. Якщо деякі сертифікати SSL неможливо перевірити, вони повідомляються як помилка «невідомий алгоритм».

  • The version of OpenSSL being used is now accessible using the module attributes ssl.OPENSSL_VERSION (a string), ssl.OPENSSL_VERSION_INFO (a 5-tuple), and ssl.OPENSSL_VERSION_NUMBER (an integer).

(Надав Антуан Пітру в bpo-8850, bpo-1589, bpo-8322, bpo-5639, bpo-4870, bpo-8484 та bpo-8321.)

nntp

Модуль nntplib має оновлену реалізацію з кращими байтами та текстовою семантикою, а також більш практичними API. Ці вдосконалення порушують сумісність із версією nntplib у Python 3.1, яка сама по собі була частково нефункціональною.

Також додано підтримку безпечних з’єднань через неявний (з використанням nntplib.NNTP_SSL) і явний (з використанням nntplib.NNTP.starttls()) TLS.

(Надано Антуаном Пітру в bpo-9360 та Ендрю Вантом у bpo-1926.)

сертифікати

http.client.HTTPSConnection, urllib.request.HTTPSHandler і urllib.request.urlopen() тепер приймають додаткові аргументи, щоб дозволити перевірку сертифіката сервера за набором центрів сертифікації, як рекомендовано для публічного використання HTTPS.

(Додав Антуан Пітру, bpo-9003.)

імапліб

Підтримку явного TLS у стандартних підключеннях IMAP4 додано за допомогою нового методу imaplib.IMAP4.starttls.

(Надано Лоренцо М. Катуччі та Антуаном Пітру, bpo-4471.)

http.client

У модулі http.client було внесено ряд невеликих покращень API. Прості відповіді HTTP 0.9 старого стилю більше не підтримуються, а параметр strict застарів у всіх класах.

Класи HTTPConnection і HTTPSConnection тепер мають параметр source_address для кортежу (хост, порт), який вказує, звідки здійснюється HTTP-з’єднання.

До HTTPSConnection додано підтримку перевірки сертифікатів і віртуальних хостів HTTPS.

Метод request() для об’єктів підключення допускав необов’язковий аргумент body, щоб file object міг використовуватися для надання вмісту запиту. Зручно те, що аргумент body тепер також приймає об’єкт iterable, якщо він містить явний заголовок Content-Length. Цей розширений інтерфейс набагато гнучкіший, ніж раніше.

Для встановлення з’єднання HTTPS через проксі-сервер існує новий метод set_tunnel(), який встановлює хост і порт для тунелювання HTTP-з’єднання.

Щоб відповідати поведінці http.server, клієнтська бібліотека HTTP тепер також кодує заголовки з кодуванням ISO-8859-1 (Latin-1). Він уже робив це для вхідних заголовків, тому тепер поведінка узгоджена як для вхідного, так і для вихідного трафіку. (Див. роботу Арміна Ронашера в bpo-10980.)

unittest

Модуль unittest має ряд удосконалень, які підтримують виявлення тестів для пакетів, спрощені експерименти в інтерактивному запиті, нові методи тестування, покращені діагностичні повідомлення про помилки тестів і кращі назви методів.

  • The command-line call python -m unittest can now accept file paths instead of module names for running specific tests (bpo-10620). The new test discovery can find tests within packages, locating any test importable from the top-level directory. The top-level directory can be specified with the -t option, a pattern for matching files with -p, and a directory to start discovery with -s:

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

    (Надав Майкл Форд.)

  • Experimentation at the interactive prompt is now easier because the unittest.TestCase class can now be instantiated without arguments:

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

    (Надав Майкл Форд.)

  • Модуль unittest має два нові методи, assertWarns() і assertWarnsRegex() для перевірки того, що певний тип попередження викликано кодом, що тестується

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

    (Надав Антуан Пітру, bpo-9754.)

    Інший новий метод, assertCountEqual(), використовується для порівняння двох ітерацій, щоб визначити, чи є їх кількість елементів рівною (чи однакові елементи присутні з однаковою кількістю входжень незалежно від порядку):

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

    (Надав Реймонд Геттінгер.)

  • Основною особливістю модуля unittest є спроба створити значущу діагностику, коли тест не вдається. Якщо це можливо, помилка записується разом із різницею виходу. Це особливо корисно для аналізу файлів журналу невдалих тестів. Однак, оскільки відмінності іноді можуть бути об’ємними, існує новий атрибут maxDiff, який встановлює максимальну довжину відображених відмінностей.

  • Крім того, назви методів у модулі зазнали ряду очищень.

    For example, assertRegex() is the new name for assertRegexpMatches() which was misnamed because the test uses re.search(), not re.match(). Other methods using regular expressions are now named using short form «Regex» in preference to «Regexp» – this matches the names used in other unittest implementations, matches Python’s old name for the re module, and it has unambiguous camel-casing.

    (Надано Реймондом Геттінгером і реалізовано Еціо Мелотті.)

  • Щоб покращити узгодженість, деякі давні псевдоніми методів застаріли на користь бажаних імен:

    Стара назва

    Бажане ім’я

    assert_()

    assertTrue()

    assertEquals()

    assertEqual()

    assertNotEquals()

    assertNotEqual()

    assertAlmostEquals()

    assertAlmostEqual()

    assertNotAlmostEquals()

    assertNotAlmostEqual()

    Likewise, the TestCase.fail* methods deprecated in Python 3.1 are expected to be removed in Python 3.3.

    (Надав Еціо Мелотті; bpo-9424.)

  • The assertDictContainsSubset() method was deprecated because it was misimplemented with the arguments in the wrong order. This created hard-to-debug optical illusions where tests like TestCase().assertDictContainsSubset({'a':1, 'b':2}, {'a':1}) would fail.

    (Надав Реймонд Геттінгер.)

випадковий

Цілочисельні методи в модулі random тепер краще справляються зі створенням рівномірних розподілів. Раніше вони обчислювали вибірку за допомогою int(n*random()), яка мала невелике зміщення щоразу, коли n не було ступенем двійки. Тепер вибір робиться з діапазону до наступного ступеня двійки, і вибір зберігається лише тоді, коли він потрапляє в діапазон 0 <= x < n. Зазначені функції та методи: randrange(), randint(), choice(), shuffle() і вибірка().

(Надав Реймонд Геттінгер; bpo-9025.)

попліб

Клас POP3_SSL тепер приймає параметр context, який є об’єктом ssl.SSLContext, який дозволяє об’єднувати параметри конфігурації SSL, сертифікати та приватні ключі в єдину (потенційно довговічну) структуру .

(Надав Джампаоло Родола; bpo-8807.)

несиндром

asyncore.dispatcher now provides a handle_accepted() method returning a (sock, addr) pair which is called when a connection has actually been established with a new remote endpoint. This is supposed to be used as a replacement for old handle_accept() and avoids the user to call accept() directly.

(Надав Джампаоло Родола; bpo-6706.)

тимчасовий файл

Модуль tempfile має новий контекстний менеджер, TemporaryDirectory, який забезпечує легке детерміноване очищення тимчасових каталогів:

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

(Надано Нілом Шеменауером і Ніком Когланом; bpo-5178.)

оглядати

  • Модуль 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'
    

    (Надано Родольфо Екхардтом і Ніком Когланом, 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>
    

(Надав Майкл Форд.)

pydoc

Модуль pydoc тепер надає значно покращений інтерфейс веб-сервера, а також новий параметр командного рядка -b для автоматичного відкриття вікна браузера для відображення цього сервера:

$ pydoc3.2 -b

(Надав Рон Адам; bpo-2001.)

дис

Модуль 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, і на власні очі побачити, що робить синтаксис мови під капотом.

(Надав Нік Коглан у bpo-9147.)

dbm

All database modules now support the get() and setdefault() methods.

(Запропоновано Реєм Алленом у bpo-9523.)

ctypes

Новий тип ctypes.c_ssize_t представляє тип даних C ssize_t.

сайт

Модуль site має три нові функції, корисні для звітування про деталі певної інсталяції Python.

  • getsitepackages() містить список усіх глобальних каталогів пакетів сайту.

  • getuserbase() повідомляє про базовий каталог користувача, де можуть зберігатися дані.

  • getusersitepackages() показує шлях до каталогу пакетів сайтів для користувача.

>>> 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'

Зручно те, що деякі функції сайту доступні безпосередньо з командного рядка:

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

(Надав Тарек Зіаде в bpo-6693.)

sysconfig

Новий модуль sysconfig дозволяє легко знаходити шляхи встановлення та змінні конфігурації, які різняться залежно від платформи та встановлення.

Модуль пропонує прості функції доступу до інформації про платформу та версію:

  • get_platform() повертає такі значення, як linux-i586 або macosx-10.6-ppc.

  • get_python_version() повертає рядок версії Python, наприклад «3.2».

It also provides access to the paths and variables corresponding to one of seven named schemes used by distutils. Those include posix_prefix, posix_home, posix_user, nt, nt_user, os2, os2_home:

  • get_paths() створює словник, що містить шляхи встановлення для поточної схеми встановлення.

  • get_config_vars() повертає словник специфічних змінних платформи.

Також є зручний інтерфейс командного рядка:

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"

(Виведено з Distutils Тареком Зіаде.)

pdb

Модуль налагоджувача pdb отримав низку покращень зручності використання:

  • pdb.py тепер має опцію -c, яка виконує команди, подані у файлі сценарію .pdbrc.

  • Файл сценарію .pdbrc може містити команди continue і next, які продовжують налагодження.

  • The Pdb class constructor now accepts a nosigint argument.

  • Нові команди: l(list), ll(long list) і source для переліку вихідного коду.

  • Нові команди: display і undisplay для показу або приховання значення виразу, якщо воно змінилося.

  • Нова команда: interact для запуску інтерактивного інтерпретатора, що містить глобальні та локальні імена, знайдені в поточній області.

  • Точки зупину можна очистити за номером точки зупину.

(Надано Георгом Брандлом, Антоніо Куні та Іллею Сендлером.)

аналізатор конфігурації

The configparser module was modified to improve usability and predictability of the default parser and its supported INI syntax. The old ConfigParser class was removed in favor of SafeConfigParser which has in turn been renamed to ConfigParser. Support for inline comments is now turned off by default and section or option duplicates are not allowed in a single configuration source.

Конфігураційні аналізатори отримали новий 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 або читання безпосередньо зі словників і рядків.

(Усі зміни внесено Łukasz Langa.)

urllib.parse

Для модуля urllib.parse було зроблено ряд покращень зручності використання.

Функція urlparse() тепер підтримує адреси IPv6, як описано в RFC 2732:

>>> 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='')

Функція urldefrag() тепер повертає 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'

Як описано в Parsing ASCII Encoded Bytes, усі функції 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'')

(Робота Ніка Коглана, Дена Мана та Сентіла Кумарана в bpo-2987, bpo-5468 та bpo-9873.)

поштова скринька

Завдяки спільним зусиллям Р. Девіда Мюррея модуль mailbox було виправлено для Python 3.2. Проблема полягала в тому, що поштова скринька спочатку була розроблена з текстовим інтерфейсом, але повідомлення електронної пошти найкраще представлено за допомогою bytes, оскільки різні частини повідомлення можуть мати різне кодування.

Рішення використовувало бінарну підтримку пакета email для аналізу довільних повідомлень електронної пошти. Крім того, рішення вимагало низки змін API.

Як і очікувалося, метод add() для об’єктів mailbox.Mailbox тепер приймає двійкове введення.

StringIO та введення текстового файлу застаріли. Крім того, введення рядка буде невдалим раніше, якщо використовуються символи, відмінні від ASCII. Раніше це не вдавалося, коли електронний лист оброблявся на наступному кроці.

Також є підтримка двійкового виведення. Метод get_file() тепер повертає файл у бінарному режимі (де раніше він неправильно встановлював файл у текстовому режимі). Існує також новий метод get_bytes(), який повертає bytes представлення повідомлення, що відповідає даному ключу.

Все ще можна отримати небінарний вихід за допомогою методу get_string() старого API, але цей підхід не дуже корисний. Натомість найкраще видобувати повідомлення з об’єкта Message або завантажувати їх із двійкового введення.

(Надано Р. Девідом Мюрреєм, зусиллями Штеффена Даоде Нурпмезо та початкового патча Віктора Стіннера в bpo-9124.)

turtledemo

The demonstration code for the turtle module was moved from the Demo directory to main library. It includes over a dozen sample scripts with lively displays. Being on sys.path, it can now be run directly from the command-line:

$ python -m turtledemo

(Переміщено з каталогу Demo Олександром Бєлопольським у bpo-10199.)

Багатопотоковість

  • Механізм серіалізації виконання одночасно запущених потоків Python (загальновідомий як GIL або глобальне блокування інтерпретатора) було переписано. Серед цілей були більш передбачувані інтервали перемикання та зменшення накладних витрат через конфлікт блокувань і кількість наступних системних викликів. Поняття «інтервал перевірки», щоб дозволити перемикання потоків, було залишено та замінено абсолютною тривалістю, вираженою в секундах. Цей параметр можна налаштувати через sys.setswitchinterval(). Зараз за замовчуванням 5 мілісекунд.

    Додаткові відомості про реалізацію можна прочитати в повідомленні списку розсилки python-dev (однак «пріоритетні запити», представлені в цьому повідомленні, не були збережені для включення).

    (Надав Антуан Пітру.)

  • Звичайні та рекурсивні блокування тепер приймають додатковий аргумент timeout для свого методу acquire(). (Надав Антуан Пітру; bpo-7316.)

  • Так само threading.Semaphore.acquire() також отримав аргумент timeout. (Надав Торстен Ландшофф; bpo-850728.)

  • Регулярне та рекурсивне отримання блокувань тепер може бути перервано сигналами на платформах, які використовують Pthreads. Це означає, що програми Python, які блокуються під час отримання блокувань, можна успішно припинити, багаторазово надсилаючи SIGINT процесу (натиснувши Ctrl+C у більшості оболонок). (Надав Рейд Клекнер; bpo-8844.)

Оптимізації

Було додано ряд невеликих покращень продуктивності:

  • Оптимізатор peephole Python тепер розпізнає шаблони, такі як x in {1, 2} як тест на приналежність до набору констант. Оптимізатор перетворює set як frozenset і зберігає попередньо зібрану константу.

    Тепер, коли покарання за швидкістю зникло, можна почати писати тести на приналежність за допомогою нотації набору. Цей стиль і семантично зрозумілий, і операційно швидкий:

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

    (Патч і додаткові тести надав Дейв Малкольм; bpo-6690).

  • Серіалізація та десеріалізація даних за допомогою модуля pickle тепер у кілька разів швидша.

    (Надано Александром Вассалотті, Антуаном Пітру та командою Unladen Swallow у bpo-9410 та bpo-3873.)

  • Алгоритм Timsort, який використовується в list.sort() і sorted(), тепер працює швидше та використовує менше пам’яті під час виклику з key function. Раніше кожен елемент списку обгортався тимчасовим об’єктом, який запам’ятовував значення ключа, пов’язане з кожним елементом. Тепер два масиви ключів і значень сортуються паралельно. Це економить пам’ять, яку споживають обгортки сортування, і економить час, втрачений на делегування порівнянь.

    (Патч Даніеля Штуцбаха в bpo-9915.)

  • Продуктивність декодування JSON покращується, а споживання пам’яті зменшується щоразу, коли той самий рядок повторюється для кількох ключів. Крім того, кодування JSON тепер використовує прискорення C, якщо аргумент sort_keys має значення true.

    (Надано Антуаном Пітру в bpo-7451 та Раймондом Геттінгером і Антуаном Пітру в bpo-10314.)

  • Рекурсивні блокування (створені за допомогою API threading.RLock()) тепер мають переваги від реалізації C, яка робить їх такими ж швидкими, як і звичайні блокування, і в 10-15 разів швидшими, ніж їхня попередня реалізація на чистому Python.

    (Надав Антуан Пітру; bpo-3001.)

  • The fast-search algorithm in stringlib is now used by the split(), rsplit(), splitlines() and replace() methods on bytes, bytearray and str objects. Likewise, the algorithm is also used by rfind(), rindex(), rsplit() and rpartition().

    (Патч від Florent Xicluna в bpo-7622 і bpo-7462.)

  • Перетворення цілого числа в рядок тепер працюють з двома «цифрами» одночасно, зменшуючи кількість операцій ділення та модуля.

    (bpo-6713, Гавейн Болтон, Марк Дікінсон і Віктор Стіннер.)

There were several other minor optimizations. Set differencing now runs faster when one operand is much larger than the other (patch by Andress Bennetts in bpo-8685). The array.repeat() method has a faster implementation (bpo-1569291 by Alexander Belopolsky). The BaseHTTPRequestHandler has more efficient buffering (bpo-3709 by Andrew Schaaf). The operator.attrgetter() function has been sped-up (bpo-10160 by Christos Georgiou). And ConfigParser loads multi-line arguments a bit faster (bpo-7113 by Łukasz Langa).

Unicode

Python has been updated to Unicode 6.0.0. The update to the standard adds over 2,000 new characters including emoji symbols which are important for mobile phones.

In addition, the updated standard has altered the character properties for two Kannada characters (U+0CF1, U+0CF2) and one New Tai Lue numeric character (U+19DA), making the former eligible for use in identifiers while disqualifying the latter. For more information, see Unicode Character Database Changes.

Кодеки

Додано підтримку cp720 арабського кодування DOS (bpo-1616979).

Кодування MBCS більше не ігнорує аргумент обробника помилок. У строгому режимі за замовчуванням він викликає UnicodeDecodeError, коли зустрічає некодовану послідовність байтів, і UnicodeEncodeError для некодованого символу.

Кодек MBCS підтримує 'strict' і 'ignore'' обробники помилок для декодування, 'strict' і 'replace' для кодування.

Щоб емулювати кодування Python3.1 MBCS, виберіть обробник 'ignore' для декодування та 'replace' обробник для кодування.

У Mac OS X Python декодує аргументи командного рядка за допомогою 'utf-8'' замість кодування локалі.

За замовчуванням tarfile використовує кодування 'utf-8' у Windows (замість 'mbcs') і 'surrogateescape' обробник помилок у всіх операційних системах.

Документація

Документація продовжує вдосконалюватися.

  • Таблицю швидких посилань було додано до верхньої частини довгих розділів, таких як Вбудовані функції. У випадку itertools посилання супроводжуються таблицями підсумків у стилі шпаргалок, щоб надати огляд і пам’ять без необхідності читати всі документи.

  • У деяких випадках чистий вихідний код Python може бути корисним доповненням до документації, тому тепер багато модулів тепер мають швидкі посилання на останню версію вихідного коду. Наприклад, документація модуля functools має швидке посилання вгорі з позначкою:

    Вихідний код Lib/functools.py.

    (Надав Реймонд Хеттінгер; див. обґрунтування.)

  • Документи тепер містять більше прикладів і рецептів. Зокрема, модуль re має великий розділ Приклади регулярних виразів. Так само модуль itertools продовжує оновлюватися новими Рецепти Itertools.

  • Модуль datetime тепер має допоміжну реалізацію на чистому Python. Функціональність не змінена. Це просто забезпечує легшу для читання альтернативну реалізацію.

    (Надав Олександр Бєлопольський у bpo-9528.)

  • Непідтримуваний каталог Demo було видалено. Деякі демонстрації було інтегровано в документацію, деякі переміщено до каталогу Tools/demo, а інші взагалі видалено.

    (Надав Георг Брандл у bpo-7962.)

ПРОСТОЮЧИЙ

  • У меню форматування тепер є опція очищення вихідних файлів шляхом видалення кінцевих пробілів.

    (Надав Реймонд Геттінгер; bpo-5150.)

  • IDLE на Mac OS X тепер працює як з Carbon AquaTk, так і з Cocoa AquaTk.

    (Надано Кевіном Волзером, Недом Дейлі та Рональдом Усореном; bpo-6075.)

Репозиторій коду

In addition to the existing Subversion code repository at https://svn.python.org there is now a Mercurial repository at https://hg.python.org/.

Після випуску 3.2 планується перехід на Mercurial як основний репозиторій. Ця розподілена система контролю версій має спростити членам спільноти створення зовнішніх наборів змін і обмін ними. Подробиці див. PEP 385.

Щоб навчитися користуватися новою системою контролю версій, перегляньте Швидкий старт або Посібник із робочих процесів Mercurial.

Зміни збірки та C API

Зміни в процесі збирання Python і в API C включають:

  • Сценарії idle, pydoc і 2to3 тепер інстальовано з суфіксом версії на make altinstall (bpo-10679).

  • Функції C, які звертаються до бази даних Unicode, тепер приймають і повертають символи з повного діапазону Unicode, навіть у вузьких збірках Unicode (Py_UNICODE_TOLOWER, Py_UNICODE_ISDECIMAL та інші). Видима відмінність у Python полягає в тому, що unicodedata.numeric() тепер повертає правильне значення для великих кодових точок, а repr() може вважати більше символів придатними для друку.

    (Повідомив Bupjoe Lee та виправив Amaury Forgeot D’Arc; bpo-5127.)

  • Обчислені gotos тепер увімкнено за замовчуванням у підтримуваних компіляторах (які визначаються сценарієм конфігурації). Їх все ще можна вибірково вимкнути, вказавши --without-computed-gotos.

    (Надав Антуан Пітру; bpo-9203.)

  • Опцію --with-wctype-functions видалено. Тепер для всіх функцій використовується вбудована база даних Unicode.

    (Надано Amaury Forgeot D’Arc; bpo-9210.)

  • Хеш-значення тепер є значеннями нового типу, Py_hash_t, який визначено таким самим розміром, що й покажчик. Раніше вони мали тип long, який у деяких 64-розрядних операційних системах досі має лише 32 біти. У результаті цього виправлення set і dict тепер можуть містити більше 2**32 записів у збірках із 64-розрядними покажчиками (раніше вони могли збільшуватися до такого розміру але їх продуктивність катастрофічно погіршилася).

    (Запропоновано Raymond Hettinger і реалізовано Benjamin Peterson; bpo-9778.)

  • A new macro Py_VA_COPY copies the state of the variable argument list. It is equivalent to C99 va_copy but available on all Python platforms (bpo-2443).

  • A new C API function PySys_SetArgvEx() allows an embedded interpreter to set sys.argv without also modifying sys.path (bpo-5753).

  • PyEval_CallObject() is now only available in macro form. The function declaration, which was kept for backwards compatibility reasons, is now removed – the macro was introduced in 1997 (bpo-8276).

  • Існує нова функція PyLong_AsLongLongAndOverflow(), яка є аналогом PyLong_AsLongAndOverflow(). Обидва вони служать для перетворення Python int на рідний тип із фіксованою шириною, забезпечуючи виявлення випадків, коли перетворення не підходить (bpo-7767).

  • Функція PyUnicode_CompareWithASCIIString() тепер повертає не дорівнює, якщо рядок Python завершується NUL.

  • Існує нова функція PyErr_NewExceptionWithDoc(), яка схожа на PyErr_NewException(), але дозволяє вказати рядок документа. Це дозволяє виняткам C мати ті самі можливості самодокументування, що й їхні чисті відповідники Python (bpo-7033).

  • При компіляції з опцією --with-valgrind розподільник pymalloc буде автоматично вимкнено під час роботи під Valgrind. Це забезпечує покращене виявлення витоку пам’яті під час роботи під Valgrind, водночас користуючись перевагами pymalloc в інший час (bpo-2422).

  • Видалено формат O? з функцій PyArg_Parse. Формат більше не використовується і ніколи не був задокументований (bpo-8837).

There were a number of other small changes to the C-API. See the Misc/NEWS file for a complete list.

Also, there were a number of updates to the Mac OS X build, see Mac/BuildScript/README.txt for details. For users running a 32/64-bit build, there is a known problem with the default Tcl/Tk on Mac OS X 10.6. Accordingly, we recommend installing an updated alternative such as ActiveState Tcl/Tk 8.5.9. See https://www.python.org/download/mac/tcltk/ for additional details.

Перенесення на Python 3.2

У цьому розділі перераховані раніше описані зміни та інші виправлення помилок, які можуть потребувати змін у вашому коді:

  • The configparser module has a number of clean-ups. The major change is to replace the old ConfigParser class with long-standing preferred alternative SafeConfigParser. In addition there are a number of smaller incompatibilities:

    • Синтаксис інтерполяції тепер перевірено в операціях get() і set(). У стандартній схемі інтерполяції дійсні лише два токени зі знаками відсотка: %(name)s і %%, причому останній є екранованим знаком відсотка.

    • Методи set() і add_section() тепер перевіряють, чи значення є фактичними рядками. Раніше непідтримувані типи могли бути введені ненавмисно.

    • Дубльовані розділи або параметри з одного джерела тепер викликають DuplicateSectionError або DuplicateOptionError. Раніше дублікати мовчки перезаписували попередній запис.

    • Вбудовані коментарі тепер вимкнено за замовчуванням, тому тепер символ ; можна безпечно використовувати у значеннях.

    • Коментарі тепер можна робити з відступом. Отже, щоб ; або # з’явилися на початку рядка в багаторядкових значеннях, їх потрібно інтерпольувати. Це запобігає помилковому сприйняттю префіксів коментарів у значеннях як коментарі.

    • "" тепер є дійсним значенням і більше не перетворюється автоматично на порожній рядок. Для порожніх рядків використовуйте "option =" у рядку.

  • Модуль nntplib було значно перероблено, що означає, що його API часто несумісні з API 3.1.

  • bytearray об’єкти більше не можна використовувати як імена файлів; натомість їх слід перетворити на bytes.

  • The array.tostring() and array.fromstring() have been renamed to array.tobytes() and array.frombytes() for clarity. The old names have been deprecated. (See bpo-8990.)

  • Функції PyArg_Parse*():

    • Формат «t#» видалено: замість нього використовуйте «s#» або «s*».

    • Формати «w» і «w#» видалено: замість них використовуйте «w*».

  • The PyCObject type, deprecated in 3.1, has been removed. To wrap opaque C pointers in Python objects, the PyCapsule API should be used instead; the new type has a well-defined interface for passing typing safety information and a less complicated signature for calling a destructor.

  • The sys.setfilesystemencoding() function was removed because it had a flawed design.

  • Функція та метод random.seed() тепер додають початкові значення рядка за допомогою хеш-функції sha512. Щоб отримати доступ до попередньої версії seed для відтворення послідовностей Python 3.1, установіть аргумент version на 1, random.seed(s, version=1).

  • The previously deprecated string.maketrans() function has been removed in favor of the static methods bytes.maketrans() and bytearray.maketrans(). This change solves the confusion around which types were supported by the string module. Now, str, bytes, and bytearray each have their own maketrans and translate methods with intermediate translation tables of the appropriate type.

    (Надав Георг Брандл; bpo-5675.)

  • The previously deprecated contextlib.nested() function has been removed in favor of a plain with statement which can accept multiple context managers. The latter technique is faster (because it is built-in), and it does a better job finalizing multiple context managers when one of them raises an exception:

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

    (Надано Георгом Брандлом і Маттіасом Брендстремом; appspot issue 53094.)

  • struct.pack() тепер дозволяє лише байти для коду пакета рядків s. Раніше він приймав текстові аргументи та неявно кодував їх у байти за допомогою UTF-8. Це було проблематично, оскільки воно робило припущення щодо правильного кодування та тому, що кодування змінної довжини може вийти з ладу під час запису в сегмент структури фіксованої довжини.

    Такий код, як struct.pack('<6sHHBBB', 'GIF87a', x, y) слід переписати, щоб використовувати байти замість тексту, struct.pack('<6sHHBBB', b'GIF87a' , x, y).

    (Виявлено Девідом Бізлі та виправлено Віктором Стіннером; bpo-10783.)

  • Клас xml.etree.ElementTree тепер викликає помилку xml.etree.ElementTree.ParseError, коли синтаксичний аналіз не вдається. Раніше це викликало xml.parsers.expat.ExpatError.

  • Нове, довше значення str() у числах з плаваючою точкою може порушити doctests, які покладаються на старий формат виводу.

  • У subprocess.Popen стандартним значенням для close_fds тепер є True під Unix; під Windows це True, якщо для трьох стандартних потоків встановлено значення None, False інакше. Раніше close_fds за замовчуванням завжди мав значення False, що створювало проблеми, які важко було вирішити, або змагання, коли дескриптори відкритого файлу потрапляли в дочірній процес.

  • Підтримку застарілого HTTP 0.9 було видалено з urllib.request і http.client. Така підтримка все ще присутня на стороні сервера (у http.server).

    (Надав Антуан Пітру, bpo-10711.)

  • SSL-сокети в режимі тайм-ауту тепер викликають socket.timeout, коли відбувається тайм-аут, а не загальну SSLError.

    (Надав Антуан Пітру, bpo-10272.)

  • The misleading functions PyEval_AcquireLock() and PyEval_ReleaseLock() have been officially deprecated. The thread-state aware APIs (such as PyEval_SaveThread() and PyEval_RestoreThread()) should be used instead.

  • Due to security risks, asyncore.handle_accept() has been deprecated, and a new function, asyncore.handle_accepted(), was added to replace it.

    (Надав Джампаоло Родола в bpo-6706.)

  • Due to the new GIL implementation, PyEval_InitThreads() cannot be called before Py_Initialize() anymore.