Що нового в Python 3.2

Автор

Raymond Hettinger

This article explains the new features in Python 3.2 as compared to 3.1. 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: Конфігурація на основі словника для журналювання

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

Щоб підтримувати більш гнучкий стиль, модуль тепер пропонує 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'
    
  • Тег, унікальний для кожного інтерпретатора, доступний з модуля imp:

    >>> import imp
    >>> imp.get_tag() 
    'cpython-32'
    
  • Сценарії, які намагаються вивести назву вихідного файлу з імпортованого файлу, тепер мають бути розумнішими. Більше недостатньо просто видалити букву «c» із імені файлу «.pyc». Замість цього використовуйте нові функції в модулі imp:

    >>> imp.source_from_cache('c:/py32/lib/__pycache__/collections.cpython-32.pyc')
    'c:/py32/lib/collections.py'
    >>> imp.cache_from_source('c:/py32/lib/collections.py') 
    'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
    
  • Модулі py_compile і compileall оновлено, щоб відобразити нову угоду про іменування та цільовий каталог. Виклик compileall у командному рядку має нові параметри: -i для вказівки списку файлів і каталогів для компіляції та -b, який змушує файли байт-коду записуватися в їх старе розташування, а не в __pycache__.

  • Модуль importlib.abc було оновлено новими абстрактними базовими класами для завантаження файлів байт-кодів. Застарілі ABC, PyLoader і PyPycLoader, стали застарілими (інструкції щодо того, як залишатися сумісними з Python 3.1, включено до документації).

Дивись також

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

Власні рядки завжди мають тип str, але обмежені кодовими точками від U+0000 до U+00FF, які можна перевести в байти за допомогою кодування Latin-1. Ці рядки використовуються для ключів і значень у словнику середовища та для заголовків відповідей і статусів у функції start_response(). Вони повинні відповідати RFC 2616 щодо кодування. Тобто вони мають бути символами ISO-8859-1 або використовувати кодування MIME RFC 2047.

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

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

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

  • Значення, отримані програмою або надіслані за допомогою методу write(), мають бути рядками байтів. Функція start_response() і середовище мають використовувати рідні рядки. Те двоє не можна змішувати.

Для розробників серверів, які пишуть шляхи CGI-to-WSGI або інші протоколи в стилі CGI, користувачі повинні мати доступ до середовища за допомогою власних рядків, навіть якщо основна платформа може мати іншу конвенцію. Щоб подолати цю прогалину, модуль wsgiref має нову функцію, wsgiref.handlers.read_environ() для перекодування змінних CGI з os.environ у рідні рядки та повернення нового словника.

Дивись також

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

  • Інтерпретатор тепер можна запустити з тихою опцією -q, щоб запобігти відображенню інформації про авторські права та версію в інтерактивному режимі. Опцію можна перевірити за допомогою атрибута sys.flags:

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

    (Надав Марчін Войдир у bpo-1772833).

  • Функція hasattr() працює, викликаючи getattr() і виявляючи, чи виникає виняткова ситуація. Ця техніка дозволяє виявляти методи, створені динамічно __getattr__() або __getattribute__(), які інакше були б відсутні у словнику класу. Раніше hasattr перехоплював будь-які винятки, можливо, маскуючи справжні помилки. Тепер hasattr було посилено, щоб перехоплювати лише AttributeError і пропускати інші винятки:

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

  • Внутрішній інструмент structsequence тепер створює підкласи кортежу. Це означає, що структури C, такі як ті, що повертаються os.stat(), time.gmtime() і sys.version_info тепер працюють як named tuple і тепер працюють з функціями та методами, які очікують кортеж як аргумент. Це великий крок вперед у тому, щоб зробити структури C такими ж гнучкими, як і їхні чисті аналоги Python:

    >>> 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, або в командному рядку.

    ResourceWarning видається під час завершення роботи інтерпретатора, якщо список gc.garbage не порожній, і якщо встановлено gc.DEBUG_UNCOLLECTABLE, друкуються всі об’єкти, які неможливо зібрати. Це має на меті повідомити програмісту, що його код містить проблеми з фіналізацією об’єктів.

    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 тепер підтримують методи index і count. Це частина зусиль, щоб більше об’єктів повністю реалізовували collections.Sequence abstract base class. У результаті мова матиме більш уніфікований API. Крім того, об’єкти range тепер підтримують нарізку та негативні індекси, навіть зі значеннями, більшими за sys.maxsize. Це робить range більш сумісним зі списками:

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

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

Пакет xml.etree.ElementTree та його аналог xml.etree.cElementTree оновлено до версії 1.3.

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

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

  • xml.etree.ElementTree.getchildren() замість цього використовуйте list(elem).

  • xml.etree.ElementTree.getiterator() замість цього використовуйте Element.iter.

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

    (Надано Реймондом Геттінгером і використано дизайнерські ідеї Джима Бейкера, Мікі Тебеки та Ніка Коглана; див. recipe 498245, recipe 577479, bpo-10586 і bpo-10593.)

  • Декоратор functools.wraps() тепер додає атрибут __wrapped__, який вказує на вихідну функцію, яку можна викликати. Це дозволяє інтроспектувати загорнуті функції. Він також копіює __annotations__, якщо визначено. І тепер він також витончено пропускає відсутні атрибути, такі як __doc__, які можуть бути не визначені для загорнутого виклику.

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

    >>> 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 включно.

  • Щоразу, коли в кортежі часу використовується двозначний рік, інтерпретація регулюється time.accept2dyear. Типовим значенням є True, що означає, що для двозначного року століття вгадується відповідно до правил POSIX, які регулюють формат strptime %y.

    Починаючи з Py3.2, використання евристики вгадування століття видасть DeprecationWarning. Замість цього рекомендується встановити time.accept2dyear на False, щоб можна було використовувати великі діапазони дат без припущень:

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

    Кілька функцій тепер мають значно розширені діапазони дат. Якщо time.accept2dyear має значення false, функція time.asctime() прийматиме будь-який рік, який вміщується в C int, тоді як time.mktime() і time. функції strftime() прийматимуть повний діапазон, що підтримується відповідними функціями операційної системи.

(Надано Олександром Бєлопольським та Віктором Стіннером у 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

Під час написання методу __repr__() для спеціального контейнера легко забути обробити випадок, коли член повертається до самого контейнера. Вбудовані об’єкти Python, такі як list і set обробляють самопосилання, відображаючи «…» у рекурсивній частині рядка представлення.

Щоб полегшити написання таких методів __repr__(), модуль reprlib має новий декоратор, recursive_repr(), для виявлення рекурсивних викликів __repr__() і заміни заповнювача рядок замість цього:

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

(Надано Реймондом Геттінгером у 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")

Якщо жодна конфігурація не налаштована до того, як відбудеться подія журналювання, тепер існує конфігурація за замовчуванням із використанням StreamHandler, спрямованого на sys.stderr для подій рівня WARNING або вище. Раніше подія, яка відбувалася до налаштування конфігурації, викликала виняток або мовчки видаляла подію залежно від значення logging.raiseExceptions. Новий обробник за замовчуванням зберігається в 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))

Деякі деталі хешування доступні через новий атрибут sys.hash_info, який описує бітову ширину хеш-значення, простий модуль, хеш-значення для infinity і nan і множник використовується для уявної частини числа:

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

Попереднє рішення щодо обмеження сумісності різних числових типів було послаблено. Досі не підтримується (і є недоцільним) мати неявне змішування в арифметичних виразах, таких як Decimal('1.1') + float('1.1'), оскільки останній втрачає інформацію в процесі побудови двійкового float. Однак, оскільки існуюче значення з плаваючою комою можна без втрат перетворити в десяткове чи раціональне представлення, має сенс додати їх до конструктора та підтримувати порівняння змішаного типу.

  • Конструктор 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)

Ще одна корисна зміна для модуля decimal полягає в тому, що атрибут Context.clamp тепер відкритий. Це корисно для створення контекстів, які відповідають десятковим форматам обміну, визначеним у IEEE 754 (див. 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.)

вибрати

Модуль select тепер надає новий постійний атрибут, PIPE_BUF, який надає мінімальну кількість байтів, які гарантовано не блокуються, коли select.select() каже труба готова до письма.

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

Крім того, клас zipfile.ZipExtFile було внутрішньо перероблено для представлення файлів, що зберігаються в архіві. Нова реалізація є значно швидшою та може бути упакована в об’єкт io.BufferedReader для більшого прискорення. Це також вирішує проблему, через яку чергувані виклики read і readline давали неправильні результати.

(Патч надіслано 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'

Деякі операційні системи дозволяють прямий доступ до закодованих байтів у середовищі. Якщо так, константа os.supports_bytes_environ буде істинною.

Для прямого доступу до закодованих змінних середовища (якщо доступно) використовуйте нову функцію 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. Він має дві нові можливості.

  • Атрибут sqlite3.Connection.in_transit має значення true, якщо є активна транзакція для незафіксованих змін.

  • Методи 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.

  • Нова функція, ssl.match_hostname(), підтримує перевірку ідентичності сервера для протоколів вищого рівня, реалізуючи правила HTTPS (від RFC 2818), які також підходять для інших протоколів.

  • 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 неможливо перевірити, вони повідомляються як помилка «невідомий алгоритм».

  • Версія OpenSSL, яка використовується, тепер доступна за допомогою атрибутів модуля: ssl.OPENSSL_VERSION (рядок), ssl.OPENSSL_VERSION_INFO (кортеж з 5) і ssl.OPENSSL_VERSION_NUMBER (ціле число).

(Надав Антуан Пітру в 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
    

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

  • Експериментувати в інтерактивній підказці тепер легше, оскільки екземпляр класу unittest.case.TestCase тепер можна створювати без аргументів:

    >>> 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, який встановлює максимальну довжину відображених відмінностей.

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

    Наприклад, assertRegex() є новою назвою для assertRegexpMatches(), яке було неправильно названо, оскільки тест використовує re.search(), а не re.match(). Інші методи, які використовують регулярні вирази, тепер називаються за допомогою короткої форми «Regex» замість «Regexp» — це відповідає назвам, які використовуються в інших реалізаціях unittest, відповідає старій назві Python для модуля re і має однозначне значення верблюжий кожух.

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

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

    Стара назва

    Бажане ім’я

    assert_()

    assertTrue()

    assertEquals()

    assertEqual()

    assertNotEquals()

    assertNotEqual()

    assertAlmostEquals()

    assertAlmostEqual()

    assertNotAlmostEquals()

    assertNotAlmostEqual()

    Так само очікується, що методи TestCase.fail*, застарілі в Python 3.1, будуть видалені в Python 3.3. Також перегляньте розділ Deprecated aliases в документації unittest.

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

  • Метод assertDictContainsSubset() визнано застарілим, оскільки його неправильно реалізовано з аргументами в неправильному порядку. Це створювало оптичні ілюзії, які важко налагодити, коли такі тести, як TestCase().assertDictContainsSubset({'a':1, 'b':2}, {'a':1}) не давали результатів.

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

випадковий

Цілочисельні методи в модулі 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

The pydoc module now provides a much-improved Web server interface, as well as a new command-line option -b to automatically open a browser window to display that server:

$ 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

Усі модулі бази даних тепер підтримують методи get() і setdefault().

(Запропоновано Реєм Алленом у 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».

Він також надає доступ до шляхів і змінних, що відповідають одній із семи названих схем, які використовує distutils. До них належать 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, які продовжують налагодження.

  • Конструктор класу Pdb тепер приймає аргумент nosigint.

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

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

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

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

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

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

Модуль configparser було змінено, щоб покращити зручність і передбачуваність синтаксичного аналізатора за замовчуванням і його підтримуваного синтаксису INI. Старий клас ConfigParser було видалено на користь SafeConfigParser, який, у свою чергу, було перейменовано на ConfigParser. Підтримку вбудованих коментарів тепер вимкнено за замовчуванням, а дублікати розділів або параметрів не допускаються в одному джерелі конфігурації.

Конфігураційні аналізатори отримали новий API на основі протоколу відображення:

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

Новий API реалізовано поверх класичного API, тому користувацькі підкласи парсерів повинні мати можливість використовувати його без змін.

Тепер можна налаштувати структуру INI-файлу, прийняту аналізаторами конфігурації. Користувачі можуть вказати альтернативні роздільники параметрів/значень і префікси коментарів, змінити назву розділу DEFAULT або змінити синтаксис інтерполяції.

Існує підтримка вбудованої інтерполяції, включаючи додатковий обробник інтерполяції ExtendedInterpolation:

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

Також було введено низку менших функцій, як-от підтримка визначення кодування в операціях читання, визначення резервних значень для функцій get або читання безпосередньо зі словників і рядків.

(Усі зміни внесено Ł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

Демонстраційний код для модуля turtle переміщено з каталогу Demo до основної бібліотеки. Він містить понад дюжину зразків сценаріїв із яскравими дисплеями. Перебуваючи на sys.path, тепер його можна запускати безпосередньо з командного рядка:

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

  • Алгоритм швидкого пошуку в stringlib тепер використовується методами split(), rsplit(), splitlines() і replace() для bytes, об’єкти bytearray і str. Подібним чином алгоритм також використовується rfind(), rindex(), rsplit() і rpartition().

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

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

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

Було ще кілька незначних оптимізацій. Розрізнення наборів тепер працює швидше, коли один операнд значно більший за інший (патч від Андресса Беннетса в bpo-8685). Метод array.repeat() має швидшу реалізацію (bpo-1569291 від Alexander Belopolsky). BaseHTTPRequestHandler має більш ефективну буферизацію (bpo-3709 від Ендрю Шаафа). Функцію operator.attrgetter() було пришвидшено (bpo-10160 від Christos Georgiou). А ConfigParser завантажує багаторядкові аргументи трохи швидше (bpo-7113 від Ł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 http://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.)

  • Новий макрос Py_VA_COPY копіює стан списку аргументів змінної. Він еквівалентний C99 va_copy, але доступний на всіх платформах Python (bpo-2443).

  • Нова функція C API PySys_SetArgvEx() дозволяє вбудованому інтерпретатору встановлювати sys.argv без зміни sys.path (bpo-5753).

  • PyEval_CallObject тепер доступний лише у формі макросу. Оголошення функції, яке було збережено з міркувань зворотної сумісності, тепер видалено — макрос було представлено в 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

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

  • Модуль configparser має ряд очищення. Основна зміна полягає в заміні старого класу ConfigParser на давню бажану альтернативу SafeConfigParser. Крім того, існує ряд менших несумісностей:

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

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

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

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

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

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

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

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

  • Для ясності array.tostring() і array.fromstring() перейменовано на array.tobytes() і array.frombytes(). Старі назви застаріли. (Див. bpo-8990.)

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

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

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

  • Тип PyCObject, застарілий у версії 3.1, було видалено. Щоб обернути непрозорі вказівники C в об’єкти Python, натомість слід використовувати API PyCapsule; новий тип має чітко визначений інтерфейс для передачі інформації про безпеку введення та менш складний підпис для виклику деструктора.

  • Функцію sys.setfilesystemencoding() було видалено, оскільки вона мала недоліки.

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

  • Раніше застарілу функцію string.maketrans() було видалено на користь статичних методів bytes.maketrans() і bytearray.maketrans(). Ця зміна вирішує плутанину навколо того, які типи підтримувалися модулем string. Тепер str, bytes і bytearray кожен має власні методи maketrans і translate із проміжними таблицями перекладу відповідного типу.

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

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

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

    (Надано Георгом Брандлом і Маттіасом Брендстремом; 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.)

  • Функції, що вводять в оману PyEval_AcquireLock() і PyEval_ReleaseLock() офіційно визнано застарілими. Замість цього слід використовувати API, що визначають стан потоку (такі як PyEval_SaveThread() і PyEval_RestoreThread()).

  • Через ризики безпеці asyncore.handle_accept() застаріло, і на його заміну додано нову функцію asyncore.handle_accepted().

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

  • Завдяки новій реалізації GIL, PyEval_InitThreads() більше не можна викликати до Py_Initialize().