Документация Python неофициальный перевод
Содержание страницы

Что нового в Python 2.3What’s New in Python 2.3

Автор:

A.M. Kuchling

В этой статье описываются новые возможности Python 2.3. Python 2.3 был выпущен 29 июля 2003 года.

Основные темы Python 2.3 – доработка некоторых возможностей, добавленных в 2.2, внесение различных небольших, но полезных улучшений в ядро языка и расширение стандартной библиотеки. Новая объектная модель, введённая в предыдущей версии, получила 18 месяцев исправлений ошибок и оптимизаций, повысивших производительность классов нового стиля. Было добавлено несколько новых встроенных функций, таких как sum() и enumerate(). Оператор in теперь можно использовать для поиска подстрок (например, "ab" in "abc" возвращает True).

Некоторые из множества новых возможностей библиотеки включают логические типы, множества, кучи, типы даты/времени, возможность импортировать модули из ZIP-архивов, поддержку метаданных для долгожданного каталога Python, обновлённую версию IDLE, а также модули для журналирования сообщений, переноса текста, разбора CSV-файлов, обработки параметров командной строки, работы с базами данных BerkeleyDB… список новых и улучшенных модулей обширен.

Эта статья не пытается дать полную спецификацию новых возможностей, а предоставляет удобный обзор. За полными подробностями следует обращаться к документации по Python 2.3, такой как «Справочник по библиотеке Python» и «Руководство по языку Python». Чтобы понять полную реализацию и обоснование дизайна, следует обратиться к PEP для конкретной новой возможности.

PEP 218: Стандартный тип данных «множество»PEP 218: A Standard Set Datatype

Новый модуль sets содержит реализацию типа данных «множество». Класс Set предназначен для изменяемых множеств, в которые можно добавлять и удалять элементы. Класс ImmutableSet – для неизменяемых множеств, и экземпляры ImmutableSet поэтому могут использоваться в качестве ключей словаря. Множества построены на основе словарей, поэтому элементы множества должны быть хешируемыми.

Вот простой пример:

>>> import sets
>>> S = sets.Set([1,2,3])
>>> S
Set([1, 2, 3])
>>> 1 in S
True
>>> 0 in S
False
>>> S.add(5)
>>> S.remove(3)
>>> S
Set([1, 2, 5])
>>>

Объединение и пересечение множеств можно вычислить с помощью методов union() и intersection(); альтернативная запись использует побитовые операторы & и |. Изменяемые множества также имеют версии этих методов, изменяющие исходное множество: union_update() и intersection_update().

>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([4,5,6])
>>> S1.union(S2)
Set([1, 2, 3, 4, 5, 6])
>>> S1 | S2                  # Альтернативная запись
Set([1, 2, 3, 4, 5, 6])
>>> S1.intersection(S2)
Set([])
>>> S1 & S2                  # Альтернативная запись
Set([])
>>> S1.union_update(S2)
>>> S1
Set([1, 2, 3, 4, 5, 6])
>>>

Также можно вычислить симметрическую разность двух множеств. Это множество всех элементов объединения, не входящих в пересечение. Другими словами, симметрическая разность содержит все элементы, которые есть ровно в одном из множеств. Опять же, существует альтернативная запись (^) и версия, изменяющая исходное множество, с неуклюжим названием symmetric_difference_update().

>>> S1 = sets.Set([1,2,3,4])
>>> S2 = sets.Set([3,4,5,6])
>>> S1.symmetric_difference(S2)
Set([1, 2, 5, 6])
>>> S1 ^ S2
Set([1, 2, 5, 6])
>>>

Также существуют методы issubset() и issuperset() для проверки, является ли одно множество подмножеством или надмножеством другого:

>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([2,3])
>>> S2.issubset(S1)
True
>>> S1.issubset(S2)
False
>>> S1.issuperset(S2)
True
>>>

См. также

PEP 218 – Добавление встроенного типа объектов-множеств

PEP написан Грегом В. Уилсоном. Реализован Грегом В. Уилсоном, Алексом Мартелли и GvR.

PEP 255: Простые генераторыPEP 255: Simple Generators

В Python 2.2 генераторы были добавлены как опциональная возможность, включаемая директивой from __future__ import generators. В версии 2.3 генераторы больше не нужно специально включать, и они теперь всегда доступны; это означает, что yield теперь всегда является ключевым словом. Остальная часть этого раздела является копией описания генераторов из документа «Что нового в Python 2.2»; если вы читали его, когда вышла версия 2.2, можете пропустить дальнейший текст.

Вызовы функций в Python или C работают привычным образом. При вызове функция получает частное пространство имён, в котором создаются её локальные переменные. Когда функция достигает оператора return, локальные переменные уничтожаются, а полученное значение возвращается вызывающему. При последующем вызове той же функции она получит новый набор локальных переменных. Но что, если бы локальные переменные не выбрасывались при выходе из функции? Что, если бы можно было возобновить выполнение функции с того места, где она остановилась? Это и обеспечивают генераторы; их можно рассматривать как возобновляемые функции.

Вот простейший пример функции-генератора:

def generate_ints(N):
    for i in range(N):
        yield i

Для генераторов было введено новое ключевое слово yield. Любая функция, содержащая оператор yield, является генераторной функцией; это обнаруживается компилятором байт-кода Python, который компилирует такую функцию особым образом.

При вызове генераторной функции она не возвращает одно значение; вместо этого она возвращает объект-генератор, поддерживающий протокол итератора. При выполнении оператора yield генератор выводит значение i, аналогично оператору return. Большая разница между yield и return состоит в том, что при достижении yield состояние выполнения генератора приостанавливается, а локальные переменные сохраняются. При следующем вызове метода .next() генератора функция возобновит выполнение сразу после оператора yield. (По сложным причинам оператор yield не допускается внутри блока try оператора tryfinally; прочитайте PEP 255 для полного объяснения взаимодействия между yield и исключениями.)

Вот пример использования генератора generate_ints():

>>> gen = generate_ints(3)
>>> gen
<generator object at 0x8117f90>
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
Traceback (most recent call last):
  File "stdin", line 1, in ?
  File "stdin", line 2, in generate_ints
StopIteration

Можно также написать for i in generate_ints(5) или a,b,c = generate_ints(3).

Внутри генераторной функции оператор return может использоваться только без значения и сигнализирует об окончании последовательности значений; после этого генератор не может вернуть никаких дополнительных значений. return со значением, например return 5, является синтаксической ошибкой внутри генераторной функции. Конец результатов генератора также можно указать вручную, возбудив StopIteration, или просто позволив потоку выполнения дойти до конца функции.

Эффекта генераторов можно добиться вручную, написав собственный класс и сохранив все локальные переменные генератора как переменные экземпляра. Например, возврат списка целых чисел можно было бы реализовать, установив self.count в 0 и заставив метод next() увеличивать self.count и возвращать его. Однако для сколь-нибудь сложного генератора написание соответствующего класса было бы гораздо более запутанным. Lib/test/test_generators.py содержит ряд более интересных примеров. Самый простой из них реализует симметричный обход дерева с помощью рекурсивных генераторов.

# Рекурсивный генератор, порождающий листья дерева в порядке in-order.
def inorder(t):
    if t:
        for x in inorder(t.left):
            yield x
        yield t.label
        for x in inorder(t.right):
            yield x

Два других примера в Lib/test/test_generators.py дают решения задачи о N ферзях (размещение N ферзей на шахматной доске N×N так, чтобы ни один ферзь не угрожал другому) и задачи об обходе коня (маршрут, по которому конь посещает каждую клетку доски N×N, не посещая ни одну клетку дважды).

Идея генераторов пришла из других языков программирования, особенно Icon (https://www2.cs.arizona.edu/icon/), где идея генераторов является центральной. В Icon каждое выражение и вызов функции ведут себя как генератор. Один пример из «Обзора языка программирования Icon» по адресу https://www2.cs.arizona.edu/icon/docs/ipd266.htm даёт представление о том, как это выглядит:

sentence := "Store it in the neighboring harbor"
if (i := find("or", sentence)) > 5 then write(i)

В Icon функция find() возвращает индексы, по которым найдена подстрока «or»: 3, 23, 33. В операторе if переменной i сначала присваивается значение 3, но 3 меньше 5, поэтому сравнение не удаётся, и Icon повторяет попытку со вторым значением 23. 23 больше 5, поэтому теперь сравнение успешно, и код выводит на экран значение 23.

Python не заходит так далеко, как Icon, в принятии генераторов в качестве центральной концепции. Генераторы считаются частью ядра языка Python, но их изучение или использование не является обязательным; если они не решают никаких проблем, их можно смело игнорировать. Одна новая особенность интерфейса Python по сравнению с Icon заключается в том, что состояние генератора представлено в виде конкретного объекта (итератора), который можно передавать другим функциям или хранить в структуре данных.

См. также

PEP 255 - Simple Generators

Авторы: Нил Шеменауэр, Тим Питерс, Магнус Ли Хетланд. Реализовано в основном Нилом Шеменауэром и Тимом Питерсом, с дополнительными исправлениями от команды Python Labs.

PEP 263: Кодировки исходного кодаPEP 263: Source Code Encodings

Файлы исходного кода Python теперь можно объявлять как файлы в различных кодировках символов. Кодировки объявляются путём включения специально отформатированного комментария в первую или вторую строку исходного файла. Например, файл в UTF-8 можно объявить с помощью:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

Без такого объявления кодировки по умолчанию используется 7-битная ASCII. Выполнение или импорт модулей, содержащих строковые литералы с 8-битными символами и не имеющих объявления кодировки, приведёт к тому, что Python 2.3 сообщит о DeprecationWarning; в версии 2.4 это будет синтаксической ошибкой.

Объявление кодировки влияет только на строковые литералы Unicode, которые будут преобразованы в Unicode с использованием указанной кодировки. Обратите внимание, что идентификаторы Python по-прежнему ограничены символами ASCII, поэтому нельзя использовать имена переменных, содержащие символы за пределами обычных буквенно-цифровых.

См. также

PEP 263 – Определение кодировок исходного кода Python

Авторы: Marc-André Lemburg и Martin von Löwis; реализовано Suzuki Hisao и Martin von Löwis.

PEP 273: Импорт модулей из ZIP-архивовPEP 273: Importing Modules from ZIP Archives

Новый модуль zipimport добавляет поддержку импорта модулей из архивов формата ZIP. Явно импортировать этот модуль не нужно; он будет импортирован автоматически, если имя файла ZIP-архива добавлено в sys.path. Например:

amk@nyman:~/src/python$ unzip -l /tmp/example.zip
Archive:  /tmp/example.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
     8467  11-26-02 22:30   jwzthreading.py
 --------                   -------
     8467                   1 file
amk@nyman:~/src/python$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32)
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'
>>>

Запись в sys.path теперь может быть именем файла ZIP-архива. ZIP-архив может содержать любые файлы, но импортировать можно только файлы с именами *.py, *.pyc или *.pyo. Если архив содержит только файлы *.py, Python не будет пытаться изменить архив, добавляя соответствующий файл *.pyc; это означает, что если ZIP-архив не содержит файлов *.pyc, импорт может быть довольно медленным.

Также можно указать путь внутри архива, чтобы импортировать только из подкаталога; например, путь /tmp/example.zip/lib/ будет импортировать только из подкаталога lib/ внутри архива.

См. также

PEP 273 – Импорт модулей из Zip-архивов

Автор: James C. Ahlstrom, он же предоставил реализацию. Python 2.3 следует спецификации из PEP 273, но использует реализацию, написанную Just van Rossum, которая применяет хуки импорта, описанные в PEP 302. См. раздел PEP 302: Новые хуки импорта для описания новых хуков импорта.

PEP 277: Поддержка имен файлов в Unicode для Windows NTPEP 277: Unicode file name support for Windows NT

В Windows NT, 2000 и XP система хранит имена файлов в виде строк Unicode. Традиционно Python представлял имена файлов как байтовые строки, что неудовлетворительно, так как делает некоторые имена файлов недоступными.

Теперь Python позволяет использовать произвольные строки Unicode (в пределах ограничений файловой системы) для всех функций, ожидающих имена файлов, наиболее заметно – для встроенной функции open(). Если в os.listdir() передается строка Unicode, Python теперь возвращает список строк Unicode. Новая функция os.getcwdu() возвращает текущий каталог в виде строки Unicode.

Байтовые строки по-прежнему работают как имена файлов, и в Windows Python будет прозрачно преобразовывать их в Unicode, используя кодировку mbcs.

Другие системы также допускают строки Unicode в качестве имен файлов, но преобразуют их в байтовые строки перед передачей системе, что может вызвать UnicodeError. Приложения могут проверить, поддерживаются ли произвольные строки Unicode в качестве имен файлов, проверив os.path.supports_unicode_filenames, логическое значение.

В MacOS os.listdir() теперь может возвращать имена файлов в Unicode.

См. также

PEP 277 – Поддержка имен файлов в Unicode для Windows NT

Автор: Neil Hodgson; реализовано Neil Hodgson, Martin von Löwis и Mark Hammond.

PEP 278: Универсальная поддержка символов новой строкиPEP 278: Universal Newline Support

Три основные операционные системы, используемые сегодня: Microsoft Windows, Apple Macintosh OS и различные производные Unix. Небольшое раздражение при кросс-платформенной работе заключается в том, что эти три платформы используют разные символы для обозначения концов строк в текстовых файлах. Unix использует перевод строки (символ ASCII 10), MacOS – возврат каретки (символ ASCII 13), а Windows – двухсимвольную последовательность: возврат каретки и перевод строки.

Файловые объекты Python теперь могут поддерживать соглашения о конце строк, отличные от того, которое используется платформой, на которой выполняется Python. Открытие файла с режимом 'U' или 'rU' откроет файл для чтения в режиме универсальных символов новой строки. Все три соглашения о конце строк будут преобразованы в '\n' в строках, возвращаемых различными методами файлов, такими как read() и readline().

Поддержка универсальных символов новой строки также используется при импорте модулей и при выполнении файла с помощью функции execfile(). Это означает, что модули Python могут быть общими для всех трех операционных систем без необходимости преобразования концов строк.

Эту функцию можно отключить при компиляции Python, указав флаг --without-universal-newlines при запуске сценария configure.

См. также

PEP 278 – Универсальная поддержка символов новой строки

Автор и разработчик: Jack Jansen.

PEP 279: enumerate()

Новая встроенная функция enumerate() сделает некоторые циклы немного понятнее. enumerate(thing), где thing – это либо итератор, либо последовательность, возвращает итератор, который будет возвращать (0, thing[0]), (1, thing[1]), (2, thing[2]) и так далее.

Типичный способ изменить каждый элемент списка выглядит так:

for i in range(len(L)):
    item = L[i]
    # ... вычислить результат на основе элемента ...
    L[i] = result

Это можно переписать с помощью enumerate() следующим образом:

for i, item in enumerate(L):
    # ... вычислить результат на основе элемента ...
    L[i] = result

См. также

PEP 279 – Встроенная функция enumerate()

Автор и разработчик: Raymond D. Hettinger.

PEP 282: Пакет loggingPEP 282: The logging Package

Стандартный пакет для ведения журналов, logging, был добавлен в Python 2.3. Он предоставляет мощный и гибкий механизм для создания записей журнала, которые затем можно фильтровать и обрабатывать различными способами. Для управления поведением журналирования программы можно использовать файл конфигурации в стандартном формате. Python включает обработчики, которые записывают записи журнала в стандартный поток ошибок, в файл или сокет, отправляют их в системный журнал или даже по электронной почте на конкретный адрес; конечно, можно также написать свои собственные классы обработчиков.

Класс Logger является основным. Большинство кода приложения будет работать с одним или несколькими объектами Logger, каждый из которых используется определенной подсистемой приложения. Каждый Logger идентифицируется по имени, и имена организованы в иерархию с использованием . в качестве разделителя компонентов. Например, могут быть экземпляры Logger с именами server, server.auth и server.network. Последние два экземпляра находятся ниже server в иерархии. Это означает, что если увеличить подробность для server или направить сообщения server в другой обработчик, изменения также применятся к записям, регистрируемым в server.auth и server.network. Также есть корневой Logger, который является родителем всех остальных регистраторов.

Для простого использования пакет logging содержит несколько удобных функций, которые всегда используют корневой журнал:

import logging

logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')

Это даёт следующий вывод:

WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down

В конфигурации по умолчанию информационные и отладочные сообщения подавляются, а вывод направляется в стандартный поток ошибок. Включить отображение информационных и отладочных сообщений можно, вызвав метод setLevel() корневого регистратора.

Обратите внимание на использование операторов форматирования строк в вызове warning(); все функции для регистрации сообщений принимают аргументы (msg, arg1, arg2, ...) и регистрируют строку, полученную в результате msg % (arg1, arg2, ...).

Существует также функция exception(), которая записывает последнюю трассировку. Любая другая функция также запишет трассировку, если указать истинное значение для ключевого аргумента exc_info.

def f():
    try:    1/0
    except: logging.exception('Problem recorded')

f()

Это даёт следующий вывод:

ERROR:root:Problem recorded
Traceback (most recent call last):
  File "t.py", line 6, in f
    1/0
ZeroDivisionError: integer division or modulo by zero

Немного более продвинутые программы используют регистратор, отличный от корневого. Функция getLogger(name) используется для получения конкретного регистратора, создавая его, если он ещё не существует. getLogger(None) возвращает корневой регистратор.

log = logging.getLogger('server')
 ...
log.info('Listening on port %i', port)
 ...
log.critical('Disk full')
 ...

Записи журнала обычно распространяются вверх по иерархии, поэтому сообщение, записанное в server.auth, также видно server и root, но Logger может предотвратить это, установив для своего атрибута propagate значение False.

Пакет logging предоставляет и другие настраиваемые классы. Когда экземпляру Logger даётся команда записать сообщение, он создаёт экземпляр LogRecord, который отправляется любому количеству различных экземпляров Handler. Регистраторы и обработчики также могут иметь прикреплённый список фильтров, и каждый фильтр может привести к игнорированию LogRecord или изменить запись перед её передачей. Когда записи наконец выводятся, экземпляры LogRecord преобразуются в текст классом Formatter. Все эти классы могут быть заменены вашими собственными специально написанными классами.

Благодаря всем этим возможностям пакет logging обеспечивает достаточную гибкость даже для самых сложных приложений. Это лишь неполный обзор его возможностей; пожалуйста, обратитесь к справочной документации пакета для получения всех подробностей. Также полезно будет прочитать PEP 282.

См. также

PEP 282 – Система логирования

Написано Vinay Sajip и Trent Mick; реализовано Vinay Sajip.

PEP 285: Логический типPEP 285: A Boolean Type

Логический тип был добавлен в Python 2.3. В модуль __builtin__ были добавлены две новые константы: True и False. (Константы True и False были добавлены во встроенные объекты в Python 2.2.1, но в версии 2.2.1 они просто установлены в целочисленные значения 1 и 0 и не являются отдельным типом.)

Объект типа для этого нового типа называется bool; его конструктор принимает любое значение Python и преобразует его в True или False.

>>> bool(1)
True
>>> bool(0)
False
>>> bool([])
False
>>> bool( (1,) )
True

Большинство модулей стандартной библиотеки и встроенных функций были изменены, чтобы возвращать логические значения.

>>> obj = []
>>> hasattr(obj, 'append')
True
>>> isinstance(obj, list)
True
>>> isinstance(obj, tuple)
False

Логический тип Python был добавлен с главной целью – сделать код понятнее. Например, если вы читаете функцию и встречаете инструкцию return 1, вы можете задаться вопросом, представляет ли 1 логическое истинное значение, индекс или коэффициент, умножающий некоторое другое значение. Однако если инструкция – return True, смысл возвращаемого значения совершенно ясен.

Логический тип Python был добавлен не для строгой проверки типов. Очень строгий язык, такой как Pascal, также не позволил бы выполнять арифметику с логическими значениями и потребовал бы, чтобы выражение в инструкции if всегда вычислялось в логический результат. Python не настолько строг и никогда не будет, как PEP 285 явно говорит. Это означает, что вы по-прежнему можете использовать любое выражение в инструкции if, даже те, которые вычисляются в список, кортеж или какой-либо случайный объект. Логический тип является подклассом класса int, поэтому арифметика с логическими значениями всё ещё работает.

>>> True + 1
2
>>> False + 1
1
>>> False * 75
0
>>> True * 75
75

Если подвести итог True и False одной фразой: это альтернативные способы записи целочисленных значений 1 и 0, с единственным отличием, что str() и repr() возвращают строки 'True' и 'False' вместо '1' и '0'.

См. также

PEP 285 – Добавление логического типа

Автор и разработчик: GvR.

PEP 293: Колбэки обработки ошибок кодековPEP 293: Codec Error Handling Callbacks

При кодировании строки Unicode в байтовую строку могут встретиться символы, которые невозможно закодировать. До сих пор Python позволял указывать обработку ошибок как «strict» (вызывается UnicodeError), «ignore» (пропуск символа) или «replace» (использование вопросительного знака в выходной строке), при этом поведением по умолчанию является «strict». Может быть желательным указать альтернативную обработку таких ошибок, например, вставку ссылки на символ XML или ссылки на сущность HTML в преобразованную строку.

Теперь Python имеет гибкую платформу для добавления различных стратегий обработки. Новые обработчики ошибок можно добавить с помощью codecs.register_error(), и после этого кодеки могут получить доступ к обработчику ошибок через codecs.lookup_error(). Эквивалентный C API был добавлен для кодеков, написанных на C. Обработчик ошибок получает необходимую информацию о состоянии, такую как преобразуемая строка, позиция в строке, где была обнаружена ошибка, и целевая кодировка. Затем обработчик может либо вызвать исключение, либо вернуть строку замены.

С помощью этой платформы были реализованы два дополнительных обработчика ошибок: «backslashreplace» использует экранирование обратной косой чертой Python для представления незакодируемых символов, а «xmlcharrefreplace» генерирует ссылки на символы XML.

См. также

PEP 293 – Колбэки обработки ошибок кодеков

Автор и разработчик: Walter Dörwald.

PEP 301: Индекс пакетов и метаданные для DistutilsPEP 301: Package Index and Metadata for Distutils

Поддержка долгожданного каталога Python впервые появляется в версии 2.3.

Сердцем каталога является новая команда Distutils register. Запуск python setup.py register собирает метаданные, описывающие пакет, такие как его имя, версию, сопровождающего, описание и т.д., и отправляет их на центральный сервер каталога. Полученный каталог доступен по адресу https://pypi.org.

Чтобы сделать каталог немного более полезным, был добавлен новый необязательный ключевой аргумент classifiers в функцию Distutils setup(). Можно указать список строк в стиле Trove, чтобы помочь классифицировать программное обеспечение.

Вот пример setup.py с классификаторами, написанный для совместимости со старыми версиями Distutils:

from distutils import core
kw = {'name': "Quixote",
      'version': "0.5.1",
      'description': "A highly Pythonic Web application framework",
      # ...
      }

if (hasattr(core, 'setup_keywords') and
    'classifiers' in core.setup_keywords):
    kw['classifiers'] = \
        ['Topic :: Internet :: WWW/HTTP :: Dynamic Content',
         'Environment :: No Input/Output (Daemon)',
         'Intended Audience :: Developers'],

core.setup(**kw)

Полный список классификаторов можно получить, запустив python setup.py register --list-classifiers.

См. также

PEP 301 – Индекс пакетов и метаданные для Distutils

Автор и разработчик: Richard Jones.

PEP 302: Новые хуки импортаPEP 302: New Import Hooks

Хотя можно было создавать собственные хуки импорта с момента появления модуля ihooks в Python 1.3, никто не был им полностью доволен, потому что написание новых хуков импорта было сложным и запутанным. Были разные предложения, такие как модули imputil и iu, но ни одно из них не получило широкого признания, и ни одно из них не было легко использовать из кода на C.

PEP 302 заимствует идеи у своих предшественников, особенно у модуля iu Гордона МакМиллана. В модуль sys добавлены три новых элемента:

  • sys.path_hooks – это список вызываемых объектов; чаще всего это будут классы. Каждый вызываемый объект принимает строку, содержащую путь, и либо возвращает объект импортёра, который будет обрабатывать импорт из этого пути, либо возбуждает исключение ImportError, если не может обработать этот путь.

  • sys.path_importer_cache кеширует объекты импортёров для каждого пути, поэтому sys.path_hooks нужно будет обойти только один раз для каждого пути.

  • sys.meta_path – это список объектов импортёров, которые будут просматриваться до проверки sys.path. Этот список изначально пуст, но пользовательский код может добавлять в него объекты. Дополнительные встроенные и замороженные модули могут быть импортированы объектом, добавленным в этот список.

Объекты импортёров должны иметь единственный метод find_module(fullname, path=None). fullname будет именем модуля или пакета, например string или distutils.core. find_module() должен возвращать объект загрузчика, который имеет единственный метод load_module(fullname), создающий и возвращающий соответствующий объект модуля.

Псевдокод новой логики импорта в Python выглядит примерно так (немного упрощён; полные подробности см. в PEP 302):

for mp in sys.meta_path:
    loader = mp(fullname)
    if loader is not None:
        <module> = loader.load_module(fullname)

for path in sys.path:
    for hook in sys.path_hooks:
        try:
            importer = hook(path)
        except ImportError:
            # ImportError, поэтому попробуем другие перехватчики путей
            pass
        else:
            loader = importer.find_module(fullname)
            <module> = loader.load_module(fullname)

# Не найдено!
raise ImportError

См. также

PEP 302 – новые хуки импорта

Автор: Just van Rossum и Paul Moore. Реализовано Just van Rossum.

PEP 305: Файлы с разделителями-запятымиPEP 305: Comma-separated Files

Файлы с разделителями-запятыми – это формат, часто используемый для экспорта данных из баз данных и электронных таблиц. В Python 2.3 добавлен синтаксический анализатор таких файлов.

Формат с разделителями-запятыми на первый взгляд обманчиво прост:

Costs,150,200,3.95

Прочитать строку и вызвать line.split(','): что может быть проще? Но если добавить строковые данные, которые могут содержать запятые, всё становится сложнее:

"Costs",150,200,3.95,"Includes taxes, shipping, and sundry items"

Большое уродливое регулярное выражение может это разобрать, но использовать новый пакет csv гораздо проще:

import csv

input = open('datafile', 'rb')
reader = csv.reader(input)
for line in reader:
    print line

Функция reader() принимает ряд различных опций. Разделитель полей не ограничивается запятой – его можно заменить на любой символ, и то же самое касается символов кавычек и окончания строки.

Можно определить и зарегистрировать различные диалекты файлов с разделителями-запятыми; в настоящее время существует два диалекта, оба используемых Microsoft Excel. Отдельный класс csv.writer будет генерировать файлы с разделителями-запятыми из последовательности кортежей или списков, заключая в кавычки строки, содержащие разделитель.

См. также

PEP 305 - API для CSV-файлов

Авторы и разработчики: Kevin Altis, Dave Cole, Andrew McNamara, Skip Montanaro, Cliff Wells.

PEP 307: Улучшения picklePEP 307: Pickle Enhancements

Модули pickle и cPickle получили некоторое внимание в ходе цикла разработки 2.3. В 2.2 классы нового стиля можно было сериализовать без труда, но они сериализовались не очень компактно; PEP 307 приводит тривиальный пример, где класс нового стиля даёт сериализованную строку в три раза длиннее, чем для классического класса.

Решением стало изобретение нового протокола pickle. Функция pickle.dumps() уже давно поддерживает флаг текст/бинарный. В 2.3 этот флаг переопределён с логического на целое число: 0 – старый текстовый формат pickle, 1 – старый бинарный формат, а 2 – новый формат, специфичный для 2.3. Новая константа pickle.HIGHEST_PROTOCOL может использоваться для выбора самого нового доступного протокола.

Десериализация больше не считается безопасной операцией. pickle в версии 2.2 предоставлял хуки для предотвращения десериализации небезопасных классов (в частности, атрибут __safe_for_unpickling__), но этот код никогда не проверялся, и поэтому в 2.3 он полностью удалён. Не следует десериализовать недоверенные данные в любой версии Python.

Чтобы снизить накладные расходы на сериализацию классов нового стиля, был добавлен новый интерфейс для настройки сериализации с использованием трёх специальных методов: __getstate__(), __setstate__() и __getnewargs__(). Полную семантику этих методов см. в PEP 307.

Для ещё большего сжатия pickle теперь можно использовать целочисленные коды вместо длинных строк для идентификации сериализованных классов. Python Software Foundation будет поддерживать список стандартизированных кодов; также существует диапазон кодов, зарезервированных для частного использования. В настоящее время коды не определены.

См. также

PEP 307 – расширения протокола pickle

Авторы и разработчики: Guido van Rossum и Tim Peters.

Расширенные срезыExtended Slices

Начиная с Python 1.4 синтаксис срезов поддерживает необязательный третий аргумент «шаг». Например, всё это допустимый синтаксис Python: L[1:10:2], L[:-1:1], L[::-1]. Это было добавлено в Python по запросу разработчиков Numerical Python, которые широко используют третий аргумент. Однако встроенные типы последовательностей Python – списки, кортежи и строки – никогда не поддерживали эту возможность, возбуждая TypeError при попытке её использовать. Майкл Хадсон внёс патч для исправления этого недостатка.

Например, теперь можно легко извлечь элементы списка с чётными индексами:

>>> L = range(10)
>>> L[::2]
[0, 2, 4, 6, 8]

Отрицательные значения также работают, чтобы создать копию того же списка в обратном порядке:

>>> L[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Это также работает для кортежей, массивов и строк:

>>> s='abcd'
>>> s[::2]
'ac'
>>> s[::-1]
'dcba'

Если у вас есть изменяемая последовательность, например список или массив, вы можете присваивать значение расширенному срезу или удалять его, но есть некоторые различия между присваиванием расширенным и обычным срезам. Присваивание обычному срезу может использоваться для изменения длины последовательности:

>>> a = range(3)
>>> a
[0, 1, 2]
>>> a[1:3] = [4, 5, 6]
>>> a
[0, 4, 5, 6]

Расширенные срезы не настолько гибки. При присваивании расширенному срезу список в правой части оператора должен содержать то же количество элементов, что и заменяемый срез:

>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> a[::2] = [0, -1]
>>> a
[0, 1, -1, 3]
>>> a[::2] = [0,1,2]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: attempt to assign sequence of size 3 to extended slice of size 2

Удаление выполняется проще:

>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> del a[::2]
>>> a
[1, 3]

Теперь также можно передавать объекты срезов методам __getitem__() встроенных последовательностей:

>>> range(10).__getitem__(slice(0, 5, 2))
[0, 2, 4]

Или использовать объекты срезов непосредственно в индексации:

>>> range(10)[slice(0, 5, 2)]
[0, 2, 4]

Чтобы упростить реализацию последовательностей, поддерживающих расширенную нарезку, объекты срезов теперь имеют метод indices(length), который, зная длину последовательности, возвращает кортеж (start, stop, step), который можно напрямую передать range(). indices() обрабатывает пропущенные и выходящие за границы индексы так же, как обычные срезы (и эта безобидная фраза скрывает множество запутанных деталей!). Метод предназначен для использования следующим образом:

class FakeSeq:
    ...
    def calc_item(self, i):
        ...
    def __getitem__(self, item):
        if isinstance(item, slice):
            indices = item.indices(len(self))
            return FakeSeq([self.calc_item(i) for i in range(*indices)])
        else:
            return self.calc_item(i)

Из этого примера также видно, что встроенный объект slice теперь является объектом типа для типа среза и больше не является функцией. Это соответствует Python 2.2, где int, str и т.д. претерпели те же изменения.

Прочие изменения языка Other Language Changes

Ниже перечислены все изменения, которые Python 2.3 вносит в ядро языка Python.

  • Оператор yield теперь всегда является ключевым словом, как описано в разделе PEP 255: Simple Generators этого документа.

  • Добавлена новая встроенная функция enumerate(), как описано в разделе PEP 279: enumerate() этого документа.

  • Добавлены две новые константы, True и False, вместе со встроенным типом bool, как описано в разделе PEP 285: A Boolean Type этого документа.

  • Конструктор типа int() теперь будет возвращать длинное целое вместо возбуждения OverflowError, когда строка или число с плавающей запятой слишком велики для целого числа. Это может привести к парадоксальному результату, что isinstance(int(expression), int) ложно, но на практике это вряд ли вызовет проблемы.

  • Встроенные типы теперь поддерживают расширенный синтаксис срезов, как описано в разделе Extended Slices этого документа.

  • Новая встроенная функция sum(iterable, start=0) суммирует числовые элементы итерируемого объекта и возвращает их сумму. sum() принимает только числа, то есть её нельзя использовать для конкатенации строк. (Автор: Alex Martelli.)

  • list.insert(pos, value) ранее вставлял value в начало списка, когда pos был отрицательным. Теперь поведение изменено для согласованности с индексацией срезов, поэтому когда pos равно -1, значение вставляется перед последним элементом и так далее.

  • list.index(value), который ищет value в списке и возвращает его индекс, теперь принимает необязательные аргументы start и stop, чтобы ограничить поиск только частью списка.

  • Словари имеют новый метод pop(key[, *default*]), который возвращает значение, соответствующее key, и удаляет эту пару ключ/значение из словаря. Если запрошенный ключ отсутствует в словаре, default возвращается, если он указан, и вызывается KeyError, если нет.

    >>> d = {1:2}
    >>> d
    {1: 2}
    >>> d.pop(4)
    Traceback (most recent call last):
      File "stdin", line 1, in ?
    KeyError: 4
    >>> d.pop(1)
    2
    >>> d.pop(1)
    Traceback (most recent call last):
      File "stdin", line 1, in ?
    KeyError: 'pop(): dictionary is empty'
    >>> d
    {}
    >>>
    

    Также есть новый метод класса dict.fromkeys(iterable, value), который создаёт словарь с ключами из предоставленного итератора iterable и всеми значениями, установленными в value, по умолчанию None.

    (Патчи предоставлены Raymond Hettinger.)

    Кроме того, конструктор dict() теперь принимает именованные аргументы для упрощения создания небольших словарей:

    >>> dict(red=1, blue=2, green=3, black=4)
    {'blue': 2, 'black': 4, 'green': 3, 'red': 1}
    

    (Автор: Just van Rossum.)

  • Оператор assert больше не проверяет флаг __debug__, поэтому отключить утверждения присваиванием __debug__ больше нельзя. Запуск Python с ключом -O по-прежнему будет генерировать код, который не выполняет никаких утверждений.

  • Большинство объектов типа теперь вызываемы, поэтому вы можете использовать их для создания новых объектов, таких как функции, классы и модули. (Это означает, что модуль new может быть объявлен устаревшим в будущей версии Python, поскольку теперь можно использовать объекты типа, доступные в модуле types.) Например, можно создать новый объект модуля следующим кодом:

    >>> import types
    >>> m = types.ModuleType('abc','docstring')
    >>> m
    <module 'abc' (built-in)>
    >>> m.__doc__
    'docstring'
    
  • Добавлено новое предупреждение PendingDeprecationWarning для указания функций, которые находятся в процессе устаревания. Предупреждение по умолчанию не будет выводиться. Чтобы проверить использование функций, которые будут устаревать в будущем, укажите -Walways::PendingDeprecationWarning:: в командной строке или используйте warnings.filterwarnings().

  • Начался процесс устаревания исключений на основе строк, как в raise "Error occurred". Возбуждение строки теперь вызывает PendingDeprecationWarning.

  • Использование None в качестве имени переменной теперь приведёт к предупреждению SyntaxWarning. В будущей версии Python None может наконец стать ключевым словом.

  • Метод xreadlines() файловых объектов, введённый в Python 2.1, больше не нужен, поскольку файлы теперь ведут себя как собственный итератор. xreadlines() изначально был введён как более быстрый способ перебора всех строк в файле, но теперь можно просто написать for line in file_obj. Файловые объекты также имеют новый атрибут encoding только для чтения, который указывает кодировку, используемую файлом; строки Unicode, записываемые в файл, будут автоматически преобразованы в байты с использованием указанной кодировки.

  • Порядок разрешения методов, используемый в классах нового стиля, изменился, хотя разницу заметят только те, у кого действительно сложная иерархия наследования. Классические классы это изменение не затрагивает. Python 2.2 изначально использовал топологическую сортировку предков класса, но 2.3 теперь использует алгоритм C3, описанный в статье «A Monotonic Superclass Linearization for Dylan». Чтобы понять причины этого изменения, прочитайте статью Микеле Симониато The Python 2.3 Method Resolution Order, или тему в python-dev, начиная с сообщения https://mail.python.org/pipermail/python-dev/2002-October/029035.html. Самуэле Педрони первым указал на проблему и реализовал исправление, написав алгоритм C3.

  • Python выполняет многопоточные программы, переключаясь между потоками после выполнения N байткодов. Значение по умолчанию для N было увеличено с 10 до 100 байткодов, что ускоряет однопоточные приложения за счёт снижения накладных расходов на переключение. Некоторые многопоточные приложения могут страдать от более медленного времени отклика, но это легко исправить, установив предел обратно на меньшее число с помощью sys.setcheckinterval(N). Предел можно получить с помощью новой функции sys.getcheckinterval().

  • Одно незначительное, но далеко идущее изменение заключается в том, что имена типов расширений, определённых модулями, входящими в состав Python, теперь содержат имя модуля и '.' в перед именем типа. Например, в Python 2.2, если вы создали сокет и вывели его __class__, вы получили бы такой вывод:

    >>> s = socket.socket()
    >>> s.__class__
    <type 'socket'>
    

    В 2.3 вы получите это:

    >>> s.__class__
    <type '_socket.socket'>
    
  • Одно из замеченных несоответствий между классами старого и нового стиля было устранено: теперь можно присваивать значения атрибутам __name__ и __bases__ классов нового стиля. Существуют некоторые ограничения на то, что можно присваивать __bases__, аналогичные тем, что относятся к присваиванию атрибуту __class__ экземпляра.

Изменения строкString Changes

  • Оператор in теперь работает со строками по-новому. Раньше при вычислении X in Y, где X и Y – строки, X могло быть только одним символом. Теперь это изменилось: X может быть строкой любой длины, и X in Y возвращает True, если X является подстрокой Y. Если X – пустая строка, результат всегда True.

    >>> 'ab' in 'abcd'
    True
    >>> 'ad' in 'abcd'
    False
    >>> '' in 'abcd'
    True
    

    Обратите внимание: это не сообщает, где начинается подстрока; если нужна эта информация, используйте строковый метод find().

  • Строковые методы strip(), lstrip() и rstrip() теперь имеют необязательный аргумент для указания удаляемых символов. По умолчанию по-прежнему удаляются все пробельные символы:

    >>> '   abc '.strip()
    'abc'
    >>> '><><abc<><><>'.strip('<>')
    'abc'
    >>> '><><abc<><><>\n'.strip('<>')
    'abc<><><>\n'
    >>> u'\u4000\u4001abc\u4000'.strip(u'\u4000')
    u'\u4001abc'
    >>>
    

    (Предложено Simon Brunning и реализовано Walter Dörwald.)

  • Строковые методы startswith() и endswith() теперь принимают отрицательные числа для параметров start и end.

  • Ещё один новый строковый метод – zfill(), изначально функция в модуле string. zfill() дополняет числовую строку нулями слева до указанной ширины. Обратите внимание, что оператор % по-прежнему гибче и мощнее, чем zfill().

    >>> '45'.zfill(4)
    '0045'
    >>> '12345'.zfill(4)
    '12345'
    >>> 'goofy'.zfill(6)
    '0goofy'
    

    (Автор: Walter Dörwald.)

  • Добавлен новый тип-объект basestring. Как 8-битные строки, так и строки Unicode наследуются от этого типа, поэтому isinstance(obj, basestring) вернёт True для строк любого вида. Это полностью абстрактный тип, поэтому нельзя создавать экземпляры basestring.

  • Интернированные строки больше не бессмертны и теперь собираются сборщиком мусора обычным образом, когда единственная ссылка на них – из внутреннего словаря интернированных строк. (Реализовано Oren Tirosh.)

ОптимизацииOptimizations

  • Создание экземпляров классов нового стиля стало намного быстрее; теперь они быстрее, чем экземпляры классических классов!

  • Метод sort() списков был существенно переписан Тимом Питерсом, и реализация стала значительно быстрее.

  • Умножение больших длинных целых чисел теперь намного быстрее благодаря реализации умножения Карацубы – алгоритма, масштабирующегося лучше, чем O(n2), необходимый для школьного алгоритма умножения. (Исходный патч от Christopher A. Craig, существенно переработан Tim Peters.)

  • Операнд SET_LINENO теперь удалён. Это может дать небольшое увеличение скорости в зависимости от особенностей компилятора. Подробнее см. раздел Другие изменения и исправления. (Удалено Michael Hudson.)

  • Объекты xrange() теперь имеют собственный итератор, что делает for i in xrange(n) немного быстрее, чем for i in range(n). (Патч от Raymond Hettinger.)

  • Был выполнен ряд небольших перестановок в различных горячих точках для повышения производительности, например, встраивание функции или удаление некоторого кода. (В основном реализовано GvR, но многие люди внесли отдельные изменения.)

Итоговый результат оптимизаций в версии 2.3: Python 2.3 выполняет тест pystone примерно на 25% быстрее, чем Python 2.2.

Новые, улучшенные и устаревшие модулиNew, Improved, and Deprecated Modules

Как обычно, стандартная библиотека Python получила ряд улучшений и исправлений ошибок. Вот частичный список наиболее заметных изменений, отсортированный по модулям в алфавитном порядке. Полный список изменений можно найти в файле Misc/NEWS в дереве исходного кода или просмотрев журналы CVS.

  • Модуль array теперь поддерживает массивы символов Unicode с использованием символа формата 'u'. Массивы также теперь поддерживают оператор присваивания += для добавления содержимого другого массива и оператор присваивания *= для повторения массива. (Автор: Jason Orendorff.)

  • Модуль bsddb заменён версией 4.1.6 пакета PyBSDDB, предоставляющего более полный интерфейс к транзакционным возможностям библиотеки BerkeleyDB.

    Старая версия модуля переименована в bsddb185 и больше не собирается автоматически; для её включения необходимо отредактировать Modules/Setup. Обратите внимание, что новый пакет bsddb предназначен для совместимости со старым модулем, поэтому обязательно сообщайте об обнаруженных несовместимостях. При обновлении до Python 2.3, если новый интерпретатор скомпилирован с новой версией базовой библиотеки BerkeleyDB, почти наверняка потребуется преобразовать файлы базы данных в новую версию. Это можно сделать довольно легко с помощью новых скриптов db2pickle.py и pickle2db.py, которые находятся в каталоге Tools/scripts дистрибутива. Если вы уже использовали пакет PyBSDDB и импортировали его как bsddb3, придётся изменить операторы import, чтобы импортировать его как bsddb.

  • Новый модуль bz2 является интерфейсом к библиотеке сжатия данных bz2. Данные, сжатые bz2, обычно меньше, чем соответствующие данные, сжатые zlib. (Автор: Gustavo Niemeyer.)

  • Набор стандартных типов даты/времени добавлен в новый модуль datetime. Подробнее см. в следующем разделе.

  • Класс Distutils Extension теперь поддерживает дополнительный аргумент конструктора с именем depends для перечисления дополнительных исходных файлов, от которых зависит расширение. Это позволяет Distutils перекомпилировать модуль, если какой-либо из зависимых файлов изменён. Например, если sampmodule.c включает заголовочный файл sample.h, объект Extension создаётся следующим образом:

    ext = Extension("samp",
                    sources=["sampmodule.c"],
                    depends=["sample.h"])
    

    Изменение sample.h приведёт к перекомпиляции модуля. (Автор: Jeremy Hylton.)

  • Другие мелкие изменения в Distutils: теперь проверяются переменные окружения CC, CFLAGS, CPP, LDFLAGS и CPPFLAGS; они используются для переопределения настроек в конфигурации Python (автор: Robert Weber).

  • Раньше модуль doctest искал тесты только в докстрингах публичных методов и функций, но теперь проверяет и приватные. Функция DocTestSuite() создаёт объект unittest.TestSuite из набора тестов doctest.

  • Новая функция gc.get_referents(object) возвращает список всех объектов, на которые ссылается object.

  • Модуль getopt получил новую функцию gnu_getopt(), которая поддерживает те же аргументы, что и существующая функция getopt(), но использует режим разбора в стиле GNU. Существующая getopt() прекращает обработку параметров, как только встречает аргумент, не являющийся параметром, а в режиме GNU обработка продолжается, то есть параметры и аргументы могут смешиваться. Например:

    >>> getopt.getopt(['-f', 'filename', 'output', '-v'], 'f:v')
    ([('-f', 'filename')], ['output', '-v'])
    >>> getopt.gnu_getopt(['-f', 'filename', 'output', '-v'], 'f:v')
    ([('-f', 'filename'), ('-v', '')], ['output'])
    

    (Автор: Peter Åstrand.)

  • Модули grp, pwd и resource теперь возвращают расширенные кортежи:

    >>> import grp
    >>> g = grp.getgrnam('amk')
    >>> g.gr_name, g.gr_gid
    ('amk', 500)
    
  • Модуль gzip теперь может обрабатывать файлы размером более 2 ГиБ.

  • Новый модуль heapq содержит реализацию алгоритма пирамидальной очереди. Пирамида (heap) – это структура данных, подобная массиву, которая хранит элементы в частично отсортированном порядке, так что для каждого индекса k выполняются условия heap[k] <= heap[2*k+1] и heap[k] <= heap[2*k+2]. Это позволяет быстро удалять наименьший элемент, а вставка нового элемента с сохранением свойства пирамиды выполняется за O(log n). (Подробнее о структуре данных «очередь с приоритетом» см. https://xlinux.nist.gov/dads//HTML/priorityque.html.)

    Модуль heapq предоставляет функции heappush() и heappop() для добавления и удаления элементов с сохранением свойства пирамиды поверх другой изменяемой последовательности Python. Вот пример с использованием списка Python:

    >>> import heapq
    >>> heap = []
    >>> for item in [3, 7, 5, 11, 1]:
    ...    heapq.heappush(heap, item)
    ...
    >>> heap
    [1, 3, 5, 11, 7]
    >>> heapq.heappop(heap)
    1
    >>> heapq.heappop(heap)
    3
    >>> heap
    [5, 7, 11]
    

    (Автор: Kevin O’Connor.)

  • Интегрированная среда разработки IDLE была обновлена с использованием кода из проекта IDLEfork (https://idlefork.sourceforge.net). Самая заметная особенность: разрабатываемый код теперь выполняется в подпроцессе, что означает отсутствие необходимости в ручных операциях reload(). Основной код IDLE был включён в стандартную библиотеку как пакет idlelib.

  • Модуль imaplib теперь поддерживает IMAP через SSL. (Авторы: Piers Lauder и Tino Lange.)

  • Модуль itertools содержит ряд полезных функций для работы с итераторами, вдохновлённых различными функциями языков ML и Haskell. Например, itertools.ifilter(predicate, iterator) возвращает все элементы итератора, для которых функция predicate() возвращает True, а itertools.repeat(obj, N) возвращает obj N раз. В модуле есть и другие функции; подробности см. в справочной документации пакета. (Автор: Raymond Hettinger.)

  • Две новые функции в модуле math, degrees(rads) и radians(degs), выполняют преобразование между радианами и градусами. Другие функции модуля math, такие как math.sin() и math.cos(), всегда требовали входные значения в радианах. Кроме того, в math.log() был добавлен необязательный аргумент base, чтобы упростить вычисление логарифмов по основаниям, отличным от e и 10. (Автор: Raymond Hettinger.)

  • Несколько новых POSIX-функций (getpgid(), killpg(), lchown(), loadavg(), major(), makedev(), minor() и mknod()) были добавлены в модуль posix, лежащий в основе модуля os. (Авторы: Gustavo Niemeyer, Geert Jansen и Denis S. Otkidach.)

  • В модуле os семейство функций *stat() теперь может сообщать доли секунды в метке времени. Такие метки времени представляются в виде чисел с плавающей точкой, аналогично значению, возвращаемому time.time().

    В ходе тестирования было обнаружено, что некоторые приложения могут сломаться, если метки времени являются числами с плавающей точкой. Для совместимости при использовании кортежного интерфейса модуля stat_result метки времени будут представляться целыми числами. При использовании именованных полей (функция, впервые появившаяся в Python 2.2) метки времени по-прежнему представляются целыми числами, если не вызвать os.stat_float_times() для включения возврата значений с плавающей точкой:

    >>> os.stat("/tmp").st_mtime
    1034791200
    >>> os.stat_float_times(True)
    >>> os.stat("/tmp").st_mtime
    1034791200.6335014
    

    В Python 2.4 значение по умолчанию изменится – всегда будут возвращаться числа с плавающей точкой.

    Разработчикам приложений следует включать эту функцию только в том случае, если все их библиотеки корректно работают с метками времени в виде чисел с плавающей точкой, или если они используют кортежный API. Если эта функция используется, её следует активировать на уровне приложения, а не пытаться включать её для каждого отдельного вызова.

  • Модуль optparse содержит новый синтаксический анализатор аргументов командной строки, который может преобразовывать значения параметров в определённый тип Python и автоматически генерировать сообщение об использовании. Подробнее см. в следующем разделе.

  • Старый и никогда не документировавшийся модуль linuxaudiodev объявлен устаревшим, и добавлена новая версия с именем ossaudiodev. Модуль был переименован, потому что звуковые драйверы OSS могут использоваться на платформах, отличных от Linux, а интерфейс также был приведён в порядок и обновлён различными способами. (Авторы: Greg Ward и Nicholas FitzRoy-Dale.)

  • Новый модуль platform содержит ряд функций, которые пытаются определить различные свойства платформы, на которой выполняется программа. Есть функции для получения архитектуры, типа процессора, версии ОС Windows и даже версии дистрибутива Linux. (Автор: Marc-André Lemburg.)

  • Объекты синтаксического анализатора, предоставляемые модулем pyexpat, теперь могут опционально буферизировать символьные данные, что приводит к меньшему числу вызовов обработчика символьных данных и, следовательно, к более высокой производительности. Установка атрибута buffer_text объекта анализатора в значение True включает буферизацию.

  • Функция sample(population, k) была добавлена в модуль random. population – это последовательность или объект xrange, содержащий элементы совокупности, а sample() выбирает k элементов из совокупности без замены выбранных элементов. k может быть любым значением до len(population). Например:

    >>> days = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'St', 'Sn']
    >>> random.sample(days, 3)      # Выбрать 3 элемента
    ['St', 'Sn', 'Th']
    >>> random.sample(days, 7)      # Выбрать 7 элементов
    ['Tu', 'Th', 'Mo', 'We', 'St', 'Fr', 'Sn']
    >>> random.sample(days, 7)      # Выбрать 7 снова
    ['We', 'Mo', 'Sn', 'Fr', 'Tu', 'St', 'Th']
    >>> random.sample(days, 8)      # Нельзя выбрать восемь
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "random.py", line 414, in sample
          raise ValueError, "sample larger than population"
    ValueError: sample larger than population
    >>> random.sample(xrange(1,10000,2), 10)   # Выбрать десять нечётных чисел меньше 10000
    [3407, 3805, 1505, 7023, 2401, 2267, 9733, 3151, 8083, 9195]
    

    Модуль random теперь использует новый алгоритм, вихрь Мерсенна (Mersenne Twister), реализованный на C. Он быстрее и более тщательно изучен, чем предыдущий алгоритм.

    (Все изменения выполнены Raymond Hettinger.)

  • Модуль readline также получил несколько новых функций: get_history_item(), get_current_history_length() и redisplay().

  • Модули rexec и Bastion объявлены мёртвыми, и попытки их импорта будут завершаться с RuntimeError. Классы нового стиля предоставляют новые способы выхода из ограниченной среды выполнения, предоставляемой rexec, и никто не заинтересован в их исправлении или не имеет на это времени. Если у вас есть приложения, использующие rexec, перепишите их для использования чего-то другого.

    (Использование Python 2.2 или 2.1 не сделает ваши приложения безопаснее, потому что в этих версиях есть известные ошибки в модуле rexec. Повторяем: если вы используете rexec, немедленно прекратите его использование.)

  • Модуль rotor объявлен устаревшим, поскольку используемый им алгоритм шифрования не считается безопасным. Если вам нужно шифрование, используйте один из нескольких доступных отдельно модулей AES для Python.

  • Модуль shutil получил функцию move(src, dest), которая рекурсивно перемещает файл или каталог в новое место.

  • Поддержка более продвинутой обработки сигналов POSIX была добавлена в модуль signal, но затем снова удалена, так как оказалось невозможно обеспечить её надёжную работу на разных платформах.

  • Модуль socket теперь поддерживает тайм-ауты. Вы можете вызвать метод settimeout(t) у объекта сокета, чтобы установить тайм-аут в t секунд. Последующие операции с сокетом, выполнение которых занимает более t секунд, будут прерваны и вызовут исключение socket.timeout.

    Первоначальная реализация тайм-аута была выполнена Tim O’Malley. Michael Gilfix интегрировал её в модуль Python socket и провёл её через длительное рецензирование. После того как код был принят, Guido van Rossum переписал его части. (Это хороший пример совместного процесса разработки в действии.)

  • В Windows модуль socket теперь поставляется с поддержкой протокола Secure Sockets Layer (SSL).

  • Значение макроса C PYTHON_API_VERSION теперь доступно на уровне Python как sys.api_version. Текущее исключение можно очистить, вызвав новую функцию sys.exc_clear().

  • Новый модуль tarfile позволяет читать и записывать архивные файлы формата tar. (Автор: Lars Gustäbel.)

  • Новый модуль textwrap содержит функции для переноса строк, содержащих абзацы текста. Функция wrap(text, width) принимает строку и возвращает список, содержащий текст, разбитый на строки длиной не более заданной ширины. Функция fill(text, width) возвращает одну строку, переформатированную так, чтобы поместиться в строки не длиннее выбранной ширины. (Как вы можете догадаться, fill() построен поверх wrap(). Например:

    >>> import textwrap
    >>> paragraph = "Not a whit, we defy augury: ... more text ..."
    >>> textwrap.wrap(paragraph, 60)
    ["Not a whit, we defy augury: there's a special providence in",
     "the fall of a sparrow. If it be now, 'tis not to come; if it",
     ...]
    >>> print textwrap.fill(paragraph, 35)
    Not a whit, we defy augury: there's
    a special providence in the fall of
    a sparrow. If it be now, 'tis not
    to come; if it be not to come, it
    will be now; if it be not now, yet
    it will come: the readiness is all.
    >>>
    

    Модуль также содержит класс TextWrapper, который реализует стратегию переноса текста. Класс TextWrapper и функции wrap() и fill() поддерживают ряд дополнительных именованных аргументов для точной настройки форматирования; за подробностями обращайтесь к документации модуля. (Предоставлено Грегом Уордом.)

  • Модули thread и threading теперь имеют сопутствующие модули dummy_thread и dummy_threading, которые предоставляют заглушку (реализацию, ничего не делающую) интерфейса модуля thread для платформ, где потоки не поддерживаются. Цель – упростить модули, учитывающие потоки (те, которые не полагаются на потоки для выполнения), поместив следующий код в начало:

    try:
        import threading as _threading
    except ImportError:
        import dummy_threading as _threading
    

    В этом примере _threading используется как имя модуля, чтобы показать, что используемый модуль не обязательно является настоящим модулем threading. Код может вызывать функции и использовать классы из _threading независимо от поддержки потоков, избегая инструкции if и делая код немного понятнее. Этот модуль не сможет волшебным образом заставить многопоточный код работать без потоков; код, который ожидает возврата или выполнения чего-либо от другого потока, просто зависнет навсегда.

  • Функция strptime() модуля time давно была источником раздражения, потому что она использует реализацию strptime() из системной библиотеки C, и на разных платформах иногда встречаются странные ошибки. Бретт Кэннон предоставил переносимую реализацию, написанную на чистом Python, которая должна вести себя одинаково на всех платформах.

  • Новый модуль timeit помогает измерить, сколько времени занимает выполнение фрагментов кода Python. Файл timeit.py можно запускать прямо из командной строки, или можно импортировать и использовать напрямую класс Timer модуля. Вот короткий пример, который выясняет, что быстрее: преобразовать 8-битную строку в Unicode путём добавления к ней пустой строки Unicode или с помощью функции unicode():

    import timeit
    
    timer1 = timeit.Timer('unicode("abc")')
    timer2 = timeit.Timer('"abc" + u""')
    
    # Провести три испытания
    print timer1.repeat(repeat=3, number=100000)
    print timer2.repeat(repeat=3, number=100000)
    
    # На моём ноутбуке это выводит:
    # [0.36831796169281006, 0.37441694736480713, 0.35304892063140869]
    # [0.17574405670166016, 0.18193507194519043, 0.17565798759460449]
    
  • Модуль Tix получил различные исправления ошибок и обновления для текущей версии пакета Tix.

  • Модуль Tkinter теперь работает с версией Tcl с поддержкой потоков. Модель многопоточности Tcl требует, чтобы виджеты можно было обрабатывать только из того потока, в котором они созданы; обращения из другого потока могут вызвать панику в Tcl. Для некоторых интерфейсов Tcl Tkinter теперь автоматически избегает этого, когда виджет обращается из другого потока: он маршализирует команду, передаёт её в правильный поток и ожидает результаты. Другие интерфейсы не могут быть обработаны автоматически, но Tkinter теперь будет возбуждать исключение при таком обращении, чтобы вы могли хотя бы узнать о проблеме. См. https://mail.python.org/pipermail/python-dev/2002-December/031107.html для более подробного объяснения этого изменения. (Реализовано Мартином фон Лёвисом.)

  • Вызов методов Tcl через _tkinter больше не возвращает только строки. Вместо этого, если Tcl возвращает другие объекты, они преобразуются в их эквиваленты на Python, если такие существуют, или оборачиваются объектом _tkinter.Tcl_Obj, если эквивалента на Python нет. Это поведение можно контролировать через метод wantobjects() объектов tkapp.

    При использовании _tkinter через модуль Tkinter (как и делают большинство приложений Tkinter), эта возможность всегда включена. Это не должно вызывать проблем совместимости, поскольку Tkinter всегда преобразовывал строковые результаты в типы Python там, где это возможно.

    Если будут обнаружены какие-либо несовместимости, старое поведение можно восстановить, установив переменную wantobjects в модуле Tkinter в значение false перед созданием первого объекта tkapp.

    import Tkinter
    Tkinter.wantobjects = 0
    

    Любые проблемы, вызванные этим изменением, следует сообщать как об ошибке.

  • В модуле UserDict появился новый класс DictMixin, который определяет все методы словаря для классов, уже имеющих минимальный интерфейс отображения. Это значительно упрощает написание классов, которые должны быть взаимозаменяемы со словарями, например, классов в модуле shelve.

    Добавление примеси в качестве суперкласса предоставляет полный интерфейс словаря всякий раз, когда класс определяет __getitem__(), __setitem__(), __delitem__() и keys(). Например:

    >>> import UserDict
    >>> class SeqDict(UserDict.DictMixin):
    ...     """Подобие словаря, реализованное с помощью списков."""
    ...     def __init__(self):
    ...         self.keylist = []
    ...         self.valuelist = []
    ...     def __getitem__(self, key):
    ...         try:
    ...             i = self.keylist.index(key)
    ...         except ValueError:
    ...             raise KeyError
    ...         return self.valuelist[i]
    ...     def __setitem__(self, key, value):
    ...         try:
    ...             i = self.keylist.index(key)
    ...             self.valuelist[i] = value
    ...         except ValueError:
    ...             self.keylist.append(key)
    ...             self.valuelist.append(value)
    ...     def __delitem__(self, key):
    ...         try:
    ...             i = self.keylist.index(key)
    ...         except ValueError:
    ...             raise KeyError
    ...         self.keylist.pop(i)
    ...         self.valuelist.pop(i)
    ...     def keys(self):
    ...         return list(self.keylist)
    ...
    >>> s = SeqDict()
    >>> dir(s)      # Посмотреть, что другие методы словаря реализованы
    ['__cmp__', '__contains__', '__delitem__', '__doc__', '__getitem__',
     '__init__', '__iter__', '__len__', '__module__', '__repr__',
     '__setitem__', 'clear', 'get', 'has_key', 'items', 'iteritems',
     'iterkeys', 'itervalues', 'keylist', 'keys', 'pop', 'popitem',
     'setdefault', 'update', 'valuelist', 'values']
    

    (Автор: Raymond Hettinger.)

  • Реализация DOM в xml.dom.minidom теперь может генерировать вывод XML в определенной кодировке, передавая необязательный аргумент encoding методам toxml() и toprettyxml() узлов DOM.

  • Модуль xmlrpclib теперь поддерживает расширение XML-RPC для обработки значений nil, таких как None в Python. Значения nil всегда поддерживаются при демаршализации ответа XML-RPC. Чтобы генерировать запросы, содержащие None, необходимо передать значение true для параметра allow_none при создании экземпляра Marshaller.

  • Новый модуль DocXMLRPCServer позволяет писать самодокументирующиеся XML-RPC-серверы. Запустите его в демонстрационном режиме (как программу), чтобы увидеть его в действии. При обращении веб-браузера к RPC-серверу генерируется документация в стиле pydoc; при обращении xmlrpclib к серверу можно вызывать реальные методы. (Предоставлено Брайаном Куинланом.)

  • Добавлена поддержка интернационализированных доменных имен (RFC 3454, 3490, 3491, 3492). Кодировка "idna" может использоваться для преобразования между доменным именем в Unicode и его ASCII-совместимой кодировкой (ACE).

    >{}>{}> u"www.Alliancefrançaise.nu".encode("idna")
    'www.xn--alliancefranaise-npb.nu'
    

    Модуль socket также был расширен для прозрачного преобразования имен хостов в Unicode в версию ACE перед передачей их в библиотеку C. Модули, работающие с именами хостов, такие как httplib и ftplib), также поддерживают Unicode-имена хостов; httplib также отправляет HTTP-заголовки Host, используя ACE-версию доменного имени. urllib поддерживает URL-адреса Unicode с не-ASCII именами хостов, если часть path URL-адреса состоит только из ASCII.

    Для реализации этого изменения были добавлены модуль stringprep, утилита mkstringprep и кодировка punycode.

Типы даты/времениDate/Time Type

Типы даты и времени, подходящие для представления временных меток, были добавлены в виде модуля datetime. Эти типы не поддерживают разные календари или множество причудливых возможностей и придерживаются только основ представления времени.

Три основных типа: date, представляющий день, месяц и год; time, состоящий из часов, минут и секунд; и datetime, который содержит все атрибуты как date, так и time. Также существует класс timedelta, представляющий разницу между двумя моментами времени, а логика часовых поясов реализуется классами, наследующими от абстрактного класса tzinfo.

Создавать экземпляры date и time можно либо передавая именованные аргументы соответствующему конструктору, например datetime.date(year=1972, month=10, day=15), либо используя один из нескольких методов класса. Например, метод класса today() возвращает текущую локальную дату.

После создания экземпляры классов даты/времени являются неизменяемыми. Существует ряд методов для создания форматированных строк из объектов:

>>> import datetime
>>> now = datetime.datetime.now()
>>> now.isoformat()
'2002-12-30T21:27:03.994956'
>>> now.ctime()  # Доступно только для date, datetime
'Mon Dec 30 21:27:03 2002'
>>> now.strftime('%Y %d %b')
'2002 30 Dec'

Метод replace() позволяет изменить одно или несколько полей экземпляра date или datetime, возвращая новый экземпляр:

>>> d = datetime.datetime.now()
>>> d
datetime.datetime(2002, 12, 30, 22, 15, 38, 827738)
>>> d.replace(year=2001, hour = 12)
datetime.datetime(2001, 12, 30, 12, 15, 38, 827738)
>>>

Экземпляры можно сравнивать, хешировать и преобразовывать в строки (результат тот же, что и у isoformat()). Экземпляры date и datetime можно вычитать друг из друга и прибавлять к экземплярам timedelta. Самая большая недостающая возможность – отсутствие в стандартной библиотеке поддержки разбора строк и получения обратно date или datetime.

За дополнительной информацией обращайтесь к справочной документации модуля. (Предоставлено Тимом Питерсом.)

Модуль optparseThe optparse Module

Модуль getopt предоставляет простой разбор аргументов командной строки. Новый модуль optparse (первоначально названный Optik) предоставляет более сложный разбор командной строки, следующий соглашениям Unix, автоматически создаёт вывод для --help и может выполнять различные действия для разных опций.

Начните с создания экземпляра OptionParser и указания ему, какие опции есть у вашей программы.

import sys
from optparse import OptionParser

op = OptionParser()
op.add_option('-i', '--input',
              action='store', type='string', dest='input',
              help='set input filename')
op.add_option('-l', '--length',
              action='store', type='int', dest='length',
              help='set maximum length of output')

Разбор командной строки затем выполняется вызовом метода parse_args().

options, args = op.parse_args(sys.argv[1:])
print options
print args

Метод возвращает объект, содержащий все значения параметров и список строк с остальными аргументами.

Теперь запуск скрипта с различными аргументами работает так, как и ожидается. Обратите внимание, что аргумент length автоматически преобразуется в целое число.

$ ./python opt.py -i data arg1
<Values at 0x400cad4c: {'input': 'data', 'length': None}>
['arg1']
$ ./python opt.py --input=data --length=4
<Values at 0x400cad2c: {'input': 'data', 'length': 4}>
[]
$

Справочное сообщение создаётся автоматически:

$ ./python opt.py --help
usage: opt.py [options]

options:
  -h, --help            show this help message and exit
  -iINPUT, --input=INPUT
                        set input filename
  -lLENGTH, --length=LENGTH
                        set maximum length of output
$

Подробнее см. документацию модуля.

Optik был написан Грегом Уордом (Greg Ward) с учётом предложений участников Getopt SIG.

Pymalloc: специализированный распределитель объектовPymalloc: A Specialized Object Allocator

Pymalloc – специализированный распределитель объектов, написанный Владимиром Марангозовым (Vladimir Marangozov). Он появился в Python 2.1. Pymalloc работает быстрее системного malloc() и потребляет меньше памяти при типичных для программ Python сценариях выделения. Распределитель использует функцию C malloc() для получения больших пулов памяти, из которых затем выделяет小块 под более мелкие запросы.

В версиях 2.1 и 2.2 pymalloc был экспериментальной функцией и не включался по умолчанию; его нужно было явно активировать при компиляции Python, передав параметр --with-pymalloc скрипту configure. В версии 2.3 pymalloc был доработан и теперь включён по умолчанию; чтобы отключить его, нужно передать --without-pymalloc.

Для кода на Python это изменение незаметно, однако pymalloc может выявить ошибки в C-расширениях. Авторам модулей-расширений на C следует тестировать свой код с включённым pymalloc, поскольку некорректный код может приводить к аварийному завершению программы.

Есть одна особенно распространённая ошибка, вызывающая проблемы. Ранее некоторые функции выделения памяти в C API Python были просто псевдонимами для malloc() и free() из библиотеки C, поэтому случайный вызов несоответствующих функций не приводил к заметным проблемам. Когда распределитель объектов включён, эти функции больше не являются псевдонимами malloc() и free(), и ошибочный вызов функции освобождения памяти может вызвать аварийный дамп. Например, если память была выделена через PyObject_Malloc(), освобождать её нужно через PyObject_Free(), а не через free(). Некоторые модули, входящие в состав Python, столкнулись с этой проблемой и были исправлены; несомненно, есть и другие сторонние модули, в которых та же ошибка.

В рамках этого изменения запутанные множественные интерфейсы для выделения памяти были объединены в два семейства API. Память, выделенная функциями одного семейства, не должна обрабатываться функциями другого. Одно семейство предназначено для выделения блоков памяти, другое – специально для выделения объектов Python.

  • Для выделения и освобождения произвольного блока памяти используйте семейство «сырая память»: PyMem_Malloc(), PyMem_Realloc() и PyMem_Free().

  • Семейство «память объектов» – это интерфейс к описанному выше механизму pymalloc, оптимизированный для большого количества «мелких» выделений: PyObject_Malloc(), PyObject_Realloc() и PyObject_Free().

  • Для выделения и освобождения объектов Python используйте семейство «объекты»: PyObject_New, PyObject_NewVar и PyObject_Del().

Благодаря большой работе Тима Питерса (Tim Peters) pymalloc в версии 2.3 также предоставляет отладочные возможности для выявления перезаписи памяти и двойного освобождения как в модулях-расширениях, так и в самом интерпретаторе. Чтобы включить эту поддержку, соберите отладочную версию интерпретатора Python, запустив configure с --with-pydebug.

В помощь разработчикам расширений в исходные тексты Python 2.3 включён заголовочный файл Misc/pymemcompat.h, позволяющий расширениям Python использовать интерфейсы выделения памяти версии 2.3 при компиляции с любой версией Python начиная с 1.5.2. Вы можете скопировать этот файл из дистрибутива исходных текстов Python и включить его в исходный код своего расширения.

См. также

https://hg.python.org/cpython/file/default/Objects/obmalloc.c

Полные подробности реализации pymalloc можно найти в комментариях в начале файла Objects/obmalloc.c в исходных текстах Python. Приведённая выше ссылка указывает на этот файл в SVN-обозревателе python.org.

Изменения в сборке и C APIBuild and C API Changes

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

  • Реализация обнаружения циклов, используемая сборщиком мусора, доказала свою стабильность, поэтому теперь она обязательна. Сборка Python без неё больше невозможна, а флаг --with-cycle-gc у скрипта configure был удалён.

  • Python теперь может быть собран как динамическая библиотека (libpython2.3.so) – для этого при запуске скрипта configure нужно указать --enable-shared. (Автор: Ondrej Palkovsky.)

  • Макросы DL_EXPORT и DL_IMPORT теперь устарели. Функции инициализации модулей-расширений Python теперь следует объявлять с помощью нового макроса PyMODINIT_FUNC, а ядро Python будет в основном использовать макросы PyAPI_FUNC и PyAPI_DATA.

  • Интерпретатор можно скомпилировать без строк документации для встроенных функций и модулей, передав --without-doc-strings скрипту configure. Это уменьшает исполняемый файл Python примерно на 10%, но при этом будет невозможно получить справку по встроенным объектам Python. (Автор: Gustavo Niemeyer.)

  • The PyArg_NoArgs() macro is now deprecated, and code that uses it should be changed. For Python 2.2 and later, the method definition table can specify the METH_NOARGS flag, signalling that there are no arguments, and the argument checking can then be removed. If compatibility with pre-2.2 versions of Python is important, the code could use PyArg_ParseTuple(args, "") instead, but this will be slower than using METH_NOARGS.

  • PyArg_ParseTuple() теперь принимает новые символы форматирования для целых чисел без знака различного размера: B для unsigned char, H для unsigned short int, I для unsigned int и K для unsigned long long.

  • Добавлена новая функция PyObject_DelItemString(mapping, char *key) как сокращение для PyObject_DelItem(mapping, PyString_New(key)).

  • Файловые объекты теперь управляют своим внутренним строковым буфером по-другому, увеличивая его экспоненциально по мере необходимости. Это привело к значительному ускорению тестов производительности в Lib/test/test_bufio.py (по некоторым измерениям, с 57 секунд до 1,7 секунды).

  • Теперь можно определить методы класса и статические методы для типа расширения C, установив флаги METH_CLASS или METH_STATIC в структуре PyMethodDef метода.

  • Python теперь включает копию исходного кода Expat XML-парсера, устраняя зависимость от системной версии или локальной установки Expat.

  • Если вы динамически создаёте объекты типов в своём расширении, учтите изменение правил, касающихся атрибутов __module__ и __name__. Кратко: нужно убедиться, что словарь типа содержит ключ '__module__'; указание имени модуля как части имени типа до последней точки больше не будет давать желаемого эффекта. Подробнее читайте в документации по API-ссылкам или в исходном коде.

Изменения, специфичные для платформPort-Specific Changes

Поддержка порта под IBM OS/2 с использованием среды выполнения EMX была объединена с основным деревом исходных текстов Python. EMX – это уровень эмуляции POSIX поверх системных API OS/2. Порт Python для EMX старается поддерживать все возможности, похожие на POSIX, предоставляемые средой выполнения EMX, и в основном это удаётся; fork() и fcntl() ограничены недостатками базового уровня эмуляции. Стандартный порт OS/2, использующий компилятор Visual Age от IBM, также получил поддержку регистрозависимой семантики импорта в рамках интеграции порта EMX в CVS. (Автор: Andrew MacIntyre.)

В MacOS большинство модулей toolbox были слабо связаны для улучшения обратной совместимости. Это означает, что модули больше не будут загружаться с ошибкой, если в текущей версии ОС отсутствует отдельная процедура. Вместо этого вызов отсутствующей процедуры вызовет исключение. (Автор: Jack Jansen.)

Файлы спецификаций RPM, находящиеся в каталоге Misc/RPM/ дистрибутива исходных текстов Python, были обновлены для версии 2.3. (Автор: Sean Reifschneider.)

Другие новые платформы, теперь поддерживаемые Python, включают AtheOS (http://www.atheos.cx/), GNU/Hurd и OpenVMS.

Другие изменения и исправленияOther Changes and Fixes

Как обычно, по всему дереву исходных кодов было разбросано множество других улучшений и исправлений ошибок. Поиск по журналам изменений CVS показывает, что между Python 2.2 и 2.3 было применено 523 патча и исправлено 514 ошибок. Оба числа, вероятно, занижены.

Некоторые из наиболее заметных изменений:

  • Если установлена переменная окружения PYTHONINSPECT, интерпретатор Python перейдёт в интерактивный режим после выполнения программы Python, как если бы Python был вызван с опцией -i. Переменную окружения можно установить до запуска интерпретатора Python, или она может быть установлена программой Python во время выполнения.

  • Скрипт regrtest.py теперь предоставляет способ разрешить «все ресурсы, кроме foo». Имя ресурса, переданное опции -u, теперь может начинаться с дефиса ('-'), что означает «удалить этот ресурс». Например, опция '-uall,-bsddb' может использоваться для включения всех ресурсов, кроме bsddb.

  • Инструменты, используемые для сборки документации, теперь работают в Cygwin, а также в Unix.

  • Опкод SET_LINENO удалён. В незапамятные времена этот опкод был нужен для генерации номеров строк в трассировках и поддержки функций трассировки (например, pdb). Начиная с Python 1.5 номера строк в трассировках вычисляются с помощью другого механизма, который работает с «python -O». Для Python 2.3 Майкл Хадсон реализовал аналогичную схему для определения момента вызова функции трассировки, полностью устранив необходимость в SET_LINENO.

    Трудно было бы заметить какие-либо различия в коде Python, кроме небольшого ускорения при запуске Python без -O.

    Расширения C, которые обращаются к полю f_lineno объектов фрейма, должны вместо этого вызывать PyCode_Addr2Line(f->f_code, f->f_lasti). Это также приведёт к тому, что код будет работать как надо при запуске с «python -O» в более ранних версиях Python.

    Интересная новая возможность: функции трассировки теперь могут присваивать значение атрибуту f_lineno объектов фрейма, изменяя следующую выполняемую строку. В отладчик pdb добавлена команда jump, использующая эту новую возможность. (Реализовано Richie Hindle.)

Перенос на Python 2.3Porting to Python 2.3

В этом разделе перечислены описанные ранее изменения, которые могут потребовать изменения кода:

  • yield теперь всегда ключевое слово; если оно используется в коде как имя переменной, необходимо выбрать другое имя.

  • Для строк X и Y, X in Y теперь работает, если X длиннее одного символа.

  • Конструктор типа int() теперь будет возвращать длинное целое число (long) вместо возбуждения исключения OverflowError, когда строка или число с плавающей точкой слишком велики для целого числа.

  • Если у вас есть строки Unicode, содержащие 8-битные символы, вы должны объявить кодировку файла (UTF-8, Latin-1 или любую другую), добавив комментарий в начало файла. См. раздел PEP 263: Кодировки исходного кода для получения дополнительной информации.

  • Вызов методов Tcl через _tkinter больше не возвращает только строки. Вместо этого, если Tcl возвращает другие объекты, эти объекты преобразуются в их эквивалент Python, если таковой существует, или оборачиваются объектом _tkinter.Tcl_Obj, если эквивалента Python не существует.

  • Большие восьмеричные и шестнадцатеричные литералы, такие как 0xffffffff, теперь вызывают FutureWarning. В настоящее время они хранятся как 32-битные числа и дают отрицательное значение, но в Python 2.4 они станут положительными длинными целыми числами.

    Есть несколько способов исправить это предупреждение. Если вам действительно нужно положительное число, просто добавьте L в конец литерала. Если вы пытаетесь получить 32-битное целое число с установленными младшими битами и ранее использовали выражение типа ~(1 << 31), вероятно, проще всего начать со всеми установленными битами и очистить нужные старшие биты. Например, чтобы очистить только старший бит (бит 31), можно написать 0xffffffffL &~(1L<<31).

  • Больше нельзя отключить assertions, присваивая значение __debug__.

  • Функция Distutils setup() получила различные новые именованные аргументы, такие как depends. Старые версии Distutils будут аварийно завершаться при передаче неизвестных ключевых слов. Решение – проверить наличие новой функции get_distutil_options() в вашем setup.py и использовать новые ключевые слова только с версией Distutils, которая их поддерживает:

    from distutils import core
    
    kw = {'sources': 'foo.c', ...}
    if hasattr(core, 'get_distutil_options'):
        kw['depends'] = ['foo.h']
    ext = Extension(**kw)
    
  • Использование None в качестве имени переменной теперь приведёт к предупреждению SyntaxWarning.

  • Имена типов расширений, определённых модулями, входящими в состав Python, теперь содержат модуль и '.' перед именем типа.

БлагодарностиAcknowledgements

Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь с различными черновиками этой статьи: Jeff Bauer, Simon Brunning, Brett Cannon, Michael Chermside, Andrew Dalke, Scott David Daniels, Fred L. Drake, Jr., David Fraser, Kelly Gerber, Raymond Hettinger, Michael Hudson, Chris Lambert, Detlef Lannert, Martin von Löwis, Andrew MacIntyre, Lalo Martins, Chad Netzer, Gustavo Niemeyer, Neal Norwitz, Hans Nowak, Chris Reedy, Francesco Ricciardi, Vinay Sajip, Neil Schemenauer, Roman Suzi, Jason Tishler, Just van Rossum.