Что нового в Python 2.3¶
- Автор
А.М. Кучлинг
В этой статье рассказывается о новых возможностях в Python 2.3. Python 2.3 был выпущен 29 июля 2003 года.
Основными темами Python 2.3 являются полировка некоторых функций, добавленных в 2.2, добавление различных небольших, но полезных улучшений в основной язык и расширение стандартной библиотеки. Новая объектная модель, представленная в предыдущей версии, выиграла от 18 месяцев исправления ошибок и от усилий по оптимизации, которые улучшили производительность классов нового стиля. Было добавлено несколько новых встроенных функций, таких как sum()
и enumerate()
. Оператор in
теперь можно использовать для поиска подстроки (например, "ab" in "abc"
возвращает True
).
Среди многих новых возможностей библиотеки - типы данных Boolean, set, heap и date/time, возможность импорта модулей из архивов ZIP-формата, поддержка метаданных для долгожданного каталога Python, обновленная версия IDLE, модули для регистрации сообщений, обертывания текста, разбора CSV файлов, обработки опций командной строки, использования баз данных BerkeleyDB… список новых и улучшенных модулей очень длинный.
В этой статье не делается попытка дать полную характеристику новых возможностей, а вместо этого представлен удобный обзор. За полной информацией следует обращаться к документации по Python 2.3, такой как Python Library Reference и Python Reference Manual. Если вы хотите понять полную реализацию и обоснование дизайна, обратитесь к PEP для конкретной новой функции.
PEP 218: Стандартный набор данных¶
Новый модуль 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()
; в альтернативной нотации используются битовые операторы &
и |
. У изменяемых множеств также есть in-place версии этих методов, 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 # Alternative notation
Set([1, 2, 3, 4, 5, 6])
>>> S1.intersection(S2)
Set([])
>>> S1 & S2 # Alternative notation
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 - Добавление встроенного типа объекта Set
PEP написан Грегом В. Уилсоном. Реализовано Грегом В. Уилсоном, Алексом Мартелли и GvR.
PEP 255: Простые генераторы¶
В Python 2.2 генераторы были добавлены как необязательная функция, включаемая директивой from __future__ import generators
. В версии 2.3 генераторы больше не нужно специально включать, теперь они присутствуют всегда; это означает, что yield
теперь всегда является ключевым словом. Остальная часть этого раздела представляет собой копию описания генераторов из документа «Что нового в Python 2.2»; если вы читали его еще во время выхода Python 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
блока оператора try
…finally
; читайте 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
содержит ряд более интересных примеров. Самый простой из них реализует обход дерева по порядку, используя рекурсивные генераторы.
# A recursive generator that generates Tree leaves in 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-Queens (размещение $N$ ферзей на шахматной доске $NxN$ так, чтобы ни один ферзь не угрожал другому) и Knight’s Tour (маршрут, который ведет коня на каждую клетку шахматной доски $NxN$, не посещая ни одну клетку дважды).
Идея генераторов пришла из других языков программирования, особенно из Icon (https://www.cs.arizona.edu/icon/), где идея генераторов является центральной. В Icon каждое выражение и вызов функции ведет себя как генератор. Один пример из «Обзора языка программирования Icon» на сайте https://www.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 - Простые генераторы
Авторы: Нил Шеменауэр, Тим Питерс, Магнус Ли Хетланд. Реализовано в основном Нилом Шеменауэром и Тимом Питерсом, другие исправления внесены командой Python Labs.
PEP 263: Кодировки исходного кода¶
Исходные файлы 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
Авторы Марк-Андре Лембург и Мартин фон Лёвис; реализовано Сузуки Хисао и Мартином фон Лёвисом.
PEP 273: Импорт модулей из ZIP-архивов¶
Новый модуль 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-архивов
Написана Джеймсом К. Алстромом, который также предоставил реализацию. Python 2.3 следует спецификации в PEP 273, но использует реализацию, написанную Джастом ван Россумом, которая использует крючки импорта, описанные в PEP 302. Описание новых крючков импорта см. в разделе PEP 302: Новые крючки импорта.
PEP 277: Поддержка имен файлов Unicode в 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()
теперь может возвращать имена файлов в Юникоде.
См.также
- PEP 277 - Поддержка имен файлов Unicode для Windows NT
Автор Нил Ходжсон; реализовано Нилом Ходжсоном, Мартином фон Лёвисом и Марком Хаммондом.
PEP 278: Универсальная поддержка новой строки¶
Сегодня используются три основные операционные системы: Microsoft Windows, Apple Macintosh OS и различные производные Unix. Небольшое раздражение при кросс-платформенной работе заключается в том, что все эти три платформы используют разные символы для обозначения концов строк в текстовых файлах. В Unix используется строчная подача (символ ASCII 10), в MacOS - возврат каретки (символ ASCII 13), а в Windows - последовательность из двух символов: возврат каретки плюс новая строка.
Файловые объекты Python теперь могут поддерживать соглашения о конце строки, отличные от тех, которые приняты в платформе, на которой запущен Python. Открытие файла с режимом 'U'
или 'rU'
приведет к открытию файла для чтения в режиме universal newlines. Все три соглашения об окончании строки будут переведены в '\n'
в строках, возвращаемых различными файловыми методами, такими как read()
и readline()
.
Универсальная поддержка новой строки также используется при импорте модулей и при выполнении файла с помощью функции execfile()
. Это означает, что модули Python могут использоваться совместно во всех трех операционных системах без необходимости преобразования окончаний строк.
Эту возможность можно отключить при компиляции Python, указав переключатель --without-universal-newlines
при запуске скрипта Python configure.
См.также
- PEP 278 - Универсальная поддержка новой строки
Написано и реализовано Джеком Янсеном.
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]
# ... compute some result based on item ...
L[i] = result
Это можно переписать с помощью enumerate()
как:
for i, item in enumerate(L):
# ... compute some result based on item ...
L[i] = result
См.также
- PEP 279 - Встроенная функция enumerate()
Написано и реализовано Раймондом Д. Хеттингером.
PEP 282: Пакет лесозаготовок¶
В Python 2.3 был добавлен стандартный пакет для записи журналов logging
. Он предоставляет мощный и гибкий механизм для создания вывода логов, которые затем могут быть отфильтрованы и обработаны различными способами. Конфигурационный файл, написанный в стандартном формате, можно использовать для управления поведением программы при записи логов. Python включает обработчики, которые будут записывать записи журнала в стандартную ошибку, в файл или сокет, отправлять их в системный журнал или даже посылать по электронной почте на определенный адрес; конечно, можно написать собственные классы обработчиков.
Класс Logger
является основным классом. Большинство кода приложения будет иметь дело с одним или несколькими объектами Logger
, каждый из которых используется определенной подсистемой приложения. Каждый Logger
идентифицируется именем, а имена организуются в иерархию с использованием .
в качестве разделителя компонентов. Например, у вас могут быть экземпляры Logger
с именами server
, server.auth
и server.network
. Последние два экземпляра находятся ниже server
в иерархии. Это означает, что если вы увеличите многословность для server
или направите сообщения server
в другой обработчик, изменения также будут применены к записям, зарегистрированным в server.auth
и server.network
. Существует также корневой Logger
, который является родителем всех остальных регистраторов.
Для простого использования пакет logging
содержит несколько удобных функций, которые всегда используют корневой log:
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 - Система протоколирования
Авторы Винай Саджип и Трент Мик; реализовано Винаем Саджипом.
PEP 285: Булевский тип¶
В Python 2.3 был добавлен тип Boolean. В модуль __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 были не добавлены ради строгой проверки типов. Очень строгий язык, такой как Паскаль, также не позволит вам выполнять арифметические действия с булевыми числами и потребует, чтобы выражение в операторе if
всегда оценивалось булевым результатом. Python не настолько строг и никогда не будет таким, о чем прямо говорит выражение PEP 285. Это означает, что вы можете использовать любое выражение в операторе if
, даже те, которые оцениваются в список, кортеж или какой-нибудь случайный объект. Тип Boolean является подклассом класса 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 - Добавление типа bool
Написано и реализовано компанией GvR.
PEP 293: Обратные вызовы для обработки ошибок кодеков¶
При кодировании строки Unicode в байтовую строку могут встречаться некодируемые символы. До сих пор Python позволял задавать обработку ошибок как «строгую» (поднимая UnicodeError
), «игнорировать» (пропуская символ) или «заменить» (используя вопросительный знак в выходной строке), причем «строгая» является поведением по умолчанию. Может быть желательно указать альтернативную обработку таких ошибок, например, вставка ссылки на символ XML или ссылки на сущность HTML в преобразованную строку.
Python теперь имеет гибкую структуру для добавления различных стратегий обработки. Новые обработчики ошибок могут быть добавлены с помощью codecs.register_error()
, а кодеки могут получить доступ к обработчику ошибок с помощью codecs.lookup_error()
. Для кодеков, написанных на языке C, был добавлен эквивалентный C API. Обработчик ошибок получает необходимую информацию о состоянии, такую как преобразуемая строка, позиция в строке, где была обнаружена ошибка, и целевая кодировка. Затем обработчик может либо выдать исключение, либо вернуть заменяющую строку.
Два дополнительных обработчика ошибок были реализованы с использованием этой структуры: «backslashreplace» использует обратную косую черту Python для представления некодируемых символов, а «xmlcharrefreplace» выдает ссылки на символы XML.
См.также
- PEP 293 - Обратные вызовы для обработки ошибок кодека
Написана и реализована Вальтером Дёрвальдом.
PEP 301: Индекс пакетов и метаданные для Distutils¶
Поддержка давно требуемого каталога Python впервые появилась в версии 2.3.
Сердцем каталога является новая команда Distutils register. Выполнение python setup.py register
соберет метаданные, описывающие пакет, такие как его имя, версия, сопровождающий, описание и т.д., и отправит их на центральный сервер каталогов. Полученный каталог доступен по адресу https://pypi.org.
Чтобы сделать каталог немного более полезным, в функцию Distutils setup()
был добавлен новый необязательный ключевой аргумент classifiers. Список строк в стиле 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
Написано и реализовано Ричардом Джонсом.
PEP 302: Новые крючки импорта¶
Хотя с тех пор, как в Python 1.3 появился модуль ihooks
, появилась возможность писать пользовательские крючки импорта, никто никогда не был по-настоящему доволен этим, потому что писать новые крючки импорта сложно и муторно. Были предложены различные альтернативы, такие как модули imputil
и iu
, но ни один из них так и не получил широкого признания, и ни один из них не был легко применим из кода на языке Си.
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, so try the other path hooks
pass
else:
loader = importer.find_module(fullname)
<module> = loader.load_module(fullname)
# Not found!
raise ImportError
См.также
- PEP 302 - Новые крючки импорта
Написано Джастом ван Россумом и Полом Муром. Реализовано Джастом ван Россумом.
PEP 305: Файлы, разделенные запятыми¶
Файлы с разделителями-запятыми - это формат, часто используемый для экспорта данных из баз данных и электронных таблиц. В 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 - CSV File API
Авторы и исполнители: Кевин Алтис, Дэйв Коул, Эндрю МакНамара, Скип Монтанаро, Клифф Уэллс.
PEP 307: Усовершенствования Pickle¶
Модули pickle
и cPickle
получили некоторое внимание во время цикла разработки 2.3. В 2.2 классы нового стиля можно было травить без проблем, но они травились не очень компактно; PEP 307 приводит тривиальный пример, когда класс нового стиля приводит к травлению строки в три раза длиннее, чем для классического класса.
Решение заключалось в изобретении нового протокола pickle. Функция pickle.dumps()
уже давно поддерживает флаг «текст или двоичное число». В версии 2.3 этот флаг переопределен из булева в целое число: 0 - старый текстовый формат pickle, 1 - старый двоичный формат, а теперь 2 - новый формат, специфичный для версии 2.3. Новая константа, pickle.HIGHEST_PROTOCOL
, может быть использована для выбора наиболее удобного протокола.
Распаковка больше не считается безопасной операцией. В версии 2.2 pickle
были предусмотрены крючки для попытки предотвратить распаковку небезопасных классов (в частности, атрибут __safe_for_unpickling__
), но этот код никогда не проверялся, и поэтому в версии 2.3 он был удален. Вы не должны распаковывать недоверенные данные ни в одной версии Python.
Чтобы уменьшить накладные расходы на пикировку для классов нового стиля, был добавлен новый интерфейс для настройки пикировки с помощью трех специальных методов: __getstate__()
, __setstate__()
и __getnewargs__()
. Обратитесь к PEP 307 за полной семантикой этих методов.
Чтобы еще больше сжать маринады, теперь можно использовать целочисленные коды вместо длинных строк для идентификации маринованных классов. Python Software Foundation будет поддерживать список стандартизированных кодов; также существует ряд кодов для частного использования. В настоящее время коды не определены.
См.также
- PEP 307 - Расширения протокола pickle
Написана и реализована Гвидо ван Россумом и Тимом Питерсом.
Расширенные срезы¶
Начиная с Python 1.4, синтаксис нарезки поддерживает необязательный третий аргумент «step» или «stride». Например, все эти аргументы являются законными в синтаксисе 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]
Для упрощения реализации последовательностей, поддерживающих расширенную нарезку, объекты slice теперь имеют метод 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
теперь является объектом типа slice и больше не является функцией. Это соответствует Python 2.2, где int
, str
и т.д. претерпели такие же изменения.
Другие языковые изменения¶
Вот все изменения, которые Python 2.3 вносит в основной язык Python.
Теперь оператор
yield
всегда является ключевым словом, как описано в разделе PEP 255: Простые генераторы данного документа.Была добавлена новая встроенная функция
enumerate()
, как описано в разделе PEP 279: enumerate() данного документа.Две новые константы,
True
иFalse
, были добавлены вместе со встроенным типомbool
, как описано в разделе PEP 285: Булевский тип данного документа.Конструктор типа
int()
теперь будет возвращать длинное целое число вместо того, чтобы выдавать ошибкуOverflowError
, когда строка или число с плавающей точкой слишком велико, чтобы поместиться в целое число. Это может привести к парадоксальному результату, чтоisinstance(int(expression), int)
ложно, но это вряд ли вызовет проблемы на практике.Встроенные типы теперь поддерживают расширенный синтаксис нарезки, как описано в разделе Расширенные срезы этого документа.
Новая встроенная функция
sum(iterable, start=0)
складывает числовые элементы в объекте iterable и возвращает их сумму. Функцияsum()
принимает только числа, что означает, что вы не можете использовать ее для конкатенации строк. (Внесено Алексом Мартелли.)list.insert(pos, value)
раньше вставляло значение в начало списка, когда pos было отрицательным. Теперь поведение изменено, чтобы соответствовать индексации срезов, поэтому, когда pos равно -1, значение будет вставлено перед последним элементом, и так далее.list.index(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
.(Нашивки предоставлены Раймондом Хеттингером.)
Также конструктор
dict()
теперь принимает аргументы в виде ключевых слов для упрощения создания небольших словарей:>>> dict(red=1, blue=2, green=3, black=4) {'blue': 2, 'black': 4, 'green': 3, 'red': 1}
(При участии Джаста ван Россума.)
Оператор
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
. В будущей версии PythonNone
может наконец стать ключевым словом.Метод
xreadlines()
для объектов файлов, введенный в Python 2.1, больше не нужен, поскольку файлы теперь ведут себя как собственный итератор.xreadlines()
был первоначально введен как более быстрый способ перебора всех строк в файле, но теперь вы можете просто написатьfor line in file_obj
. Объекты файлов также имеют новый атрибут только для чтенияencoding
, который указывает кодировку, используемую файлом; строки Unicode, записанные в файл, будут автоматически преобразованы в байты с использованием указанной кодировки.Порядок разрешения методов, используемый классами нового стиля, изменился, хотя вы заметите разницу, только если у вас очень сложная иерархия наследования. Классические классы это изменение не затрагивает. Первоначально в Python 2.2 использовалась топологическая сортировка предков класса, но теперь в 2.3 используется алгоритм C3, описанный в статье «A Monotonic Superclass Linearization for Dylan». Чтобы понять мотивацию этого изменения, прочитайте статью Микеле Симионато «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__
экземпляра.
Изменения в строке¶
Оператор
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' >>>
(Предложено Саймоном Брюнингом и реализовано Вальтером Дёрвальдом.)
Строковые методы
startswith()
иendswith()
теперь принимают отрицательные числа для параметров start и end.Еще один новый строковый метод -
zfill()
, первоначально являвшийся функцией модуляstring
.zfill()
заполняет числовую строку нулями слева до заданной ширины. Обратите внимание, что оператор%
по-прежнему более гибкий и мощный, чемzfill()
.>>> '45'.zfill(4) '0045' >>> '12345'.zfill(4) '12345' >>> 'goofy'.zfill(6) '0goofy'
(При участии Вальтера Дёрвальда.)
Добавлен новый объект типа
basestring
. От этого типа наследуются как 8-битные строки, так и строки Unicode, поэтомуisinstance(obj, basestring)
будет возвращатьTrue
для любого типа строк. Это полностью абстрактный тип, поэтому вы не можете создавать экземплярыbasestring
.Интернированные строки больше не бессмертны и теперь будут собираться в мусор обычным способом, если единственная ссылка на них содержится во внутреннем словаре интернированных строк. (Реализовано Ореном Тирошем.)
Оптимизации¶
Создание экземпляров классов нового стиля стало намного быстрее; теперь они создаются быстрее, чем классические классы!
Метод
sort()
для объектов списка был значительно переписан Тимом Питерсом, и его реализация стала значительно быстрее.Умножение больших длинных целых чисел теперь выполняется намного быстрее благодаря реализации умножения Карацубы, алгоритма, который масштабируется лучше, чем O(n*n), требуемое для алгоритма умножения, используемого в школе. (Оригинальный патч Кристофера А. Крейга, значительно переработанный Тимом Питерсом).
Опкод
SET_LINENO
теперь отсутствует. Это может дать небольшой прирост скорости, в зависимости от особенностей вашего компилятора. См. раздел Другие изменения и исправления для более подробного объяснения. (Удалено Майклом Хадсоном.)Объекты
xrange()
теперь имеют свой собственный итератор, что делаетfor i in xrange(n)
немного быстрее, чемfor i in range(n)
. (Исправление внесено Раймондом Хеттингером.)Для повышения производительности в различных местах было сделано несколько небольших перестановок, например, инлайнинг функции или удаление некоторого кода. (Реализовано в основном GvR, но многие люди внесли отдельные изменения).
Чистым результатом оптимизации в версии 2.3 стало то, что Python 2.3 выполняет тест pystone примерно на 25% быстрее, чем Python 2.2.
Новые, улучшенные и устаревшие модули¶
Как обычно, стандартная библиотека Python получила ряд улучшений и исправлений ошибок. Вот неполный список наиболее заметных изменений, отсортированный в алфавитном порядке по имени модуля. За более полным списком изменений обратитесь к файлу Misc/NEWS
в дереве исходных текстов или просмотрите журналы CVS, чтобы узнать все подробности.
Модуль
array
теперь поддерживает массивы символов Юникода с использованием символа формата'u'
. Массивы также теперь поддерживают использование оператора присваивания+=
для добавления содержимого другого массива и оператора присваивания*=
для повторения массива. (Внесено Джейсоном Орендорфом.)Модуль
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
-сжатые данные. (Внесено Густаво Нимейером.)Набор стандартных типов даты/времени был добавлен в новый модуль
datetime
. Более подробную информацию смотрите в следующем разделе.Класс Distutils
Extension
теперь поддерживает дополнительный аргумент конструктора с именем depends для перечисления дополнительных исходных файлов, от которых зависит расширение. Это позволяет Distutils перекомпилировать модуль, если какой-либо из зависимых файлов будет изменен. Например, еслиsampmodule.c
включает заголовочный файлsample.h
, вы создадите объектExtension
следующим образом:ext = Extension("samp", sources=["sampmodule.c"], depends=["sample.h"])
Изменение
sample.h
приведет к перекомпиляции модуля. (Внесено Джереми Хилтоном.)Другие незначительные изменения в Distutils: теперь он проверяет наличие переменных окружения
CC
,CFLAGS
,CPP
,LDFLAGS
иCPPFLAGS
, используя их для переопределения настроек в конфигурации Python (вклад Роберта Вебера).Если раньше модуль
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'])
(При участии Петера Остранда.)
Модули
grp
,pwd
иresource
теперь возвращают расширенные кортежи:>>> import grp >>> g = grp.getgrnam('amk') >>> g.gr_name, g.gr_gid ('amk', 500)
Модуль
gzip
теперь может обрабатывать файлы размером более 2 Гб.Новый модуль
heapq
содержит реализацию алгоритма очереди кучи. Куча - это массивоподобная структура данных, которая хранит элементы в частично отсортированном порядке так, что для каждого индекса k,heap[k] <= heap[2*k+1]
иheap[k] <= heap[2*k+2]
. Это позволяет быстро удалить наименьший элемент, а вставка нового элемента с сохранением свойства кучи выполняется за O(lg 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]
(При участии Кевина О’Коннора.)
Интегрированная среда разработки IDLE была обновлена с использованием кода из проекта IDLEfork (http://idlefork.sourceforge.net). Наиболее заметной особенностью является то, что разрабатываемый код теперь выполняется в подпроцессе, что означает, что больше нет необходимости в ручных операциях
reload()
. Основной код IDLE был включен в стандартную библиотеку в виде пакетаidlelib
.Модуль
imaplib
теперь поддерживает IMAP через SSL. (Вклад внесли Пирс Лаудер и Тино Ланге.)itertools
содержит ряд полезных функций для использования с итераторами, вдохновленных различными функциями, предоставляемыми языками ML и Haskell. Например,itertools.ifilter(predicate, iterator)
возвращает все элементы в итераторе, для которых функцияpredicate()
возвращаетTrue
, аitertools.repeat(obj, N)
возвращаетobj
N раз. В модуле имеется ряд других функций; подробности см. в справочной документации к пакету. (Внесено Раймондом Хеттингером.)Две новые функции в модуле
math
,degrees(rads)
иradians(degs)
, конвертируют между радианами и градусами. Другие функции в модулеmath
, такие какmath.sin()
иmath.cos()
, всегда требовали входных значений, измеряемых в радианах. Также вmath.log()
был добавлен необязательный аргумент base, чтобы облегчить вычисление логарифмов для оснований, отличных отe
и10
. (Внесено Раймондом Хеттингером.)Несколько новых функций POSIX (
getpgid()
,killpg()
,lchown()
,loadavg()
,major()
,makedev()
,minor()
иmknod()
) были добавлены в модульposix
, который лежит в основе модуляos
. (При участии Густаво Нимейера, Геерта Янсена и Дениса С. Откидаха).В модуле
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, а интерфейс также был приведен в порядок и обновлен различными способами. (Вклад внесли Грег Уорд и Николас Фицрой-Дейл).Новый модуль
platform
содержит ряд функций, которые пытаются определить различные свойства платформы, на которой вы работаете. Есть функции для получения архитектуры, типа процессора, версии ОС Windows и даже версии дистрибутива Linux. (Внесено Марком-Андре Лембургом.)Объекты парсера, предоставляемые модулем
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) # Choose 3 elements ['St', 'Sn', 'Th'] >>> random.sample(days, 7) # Choose 7 elements ['Tu', 'Th', 'Mo', 'We', 'St', 'Fr', 'Sn'] >>> random.sample(days, 7) # Choose 7 again ['We', 'Mo', 'Sn', 'Fr', 'Tu', 'St', 'Th'] >>> random.sample(days, 8) # Can't choose eight 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) # Choose ten odd nos. under 10000 [3407, 3805, 1505, 7023, 2401, 2267, 9733, 3151, 8083, 9195]
Модуль
random
теперь использует новый алгоритм, Mersenne Twister, реализованный на языке C. Он быстрее и более подробно изучен, чем предыдущий алгоритм.(Все изменения внесены Раймондом Хеттингером).
Модуль
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
.Первоначальная реализация тайм-аута была сделана Тимом О’Мэлли. Майкл Гилфикс интегрировал ее в модуль Python
socket
и провел ее через длительное рецензирование. После того как код был проверен, Гвидо ван Россум переписал его часть. (Это хороший пример процесса совместной разработки в действии).В Windows модуль
socket
теперь поставляется с поддержкой Secure Sockets Layer (SSL).Значение макроса C
PYTHON_API_VERSION
теперь отображается на уровне Python какsys.api_version
. Текущее исключение может быть устранено вызовом новой функцииsys.exc_clear()
.Новый модуль
tarfile
позволяет читать из и записывать в архивные файлы формата tar. (Внесено Ларсом Густебелем.)Новый модуль
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
и делая код немного понятнее. Этот модуль не заставит многопоточный код работать без потоков; код, который ожидает возвращения другого потока или выполнения какого-либо действия, будет просто висеть вечно.Функция
time
модуляstrptime()
долгое время вызывала раздражение, поскольку она использует реализациюstrptime()
библиотеки платформы C, а на разных платформах иногда возникают странные ошибки. Бретт Кэннон предложил переносимую реализацию, которая написана на чистом Python и должна вести себя одинаково на всех платформах.Новый модуль
timeit
помогает измерить, как долго выполняются фрагменты кода Python. Файлtimeit.py
может быть запущен непосредственно из командной строки, или класс модуляTimer
может быть импортирован и использован напрямую. Вот короткий пример, в котором выясняется, как быстрее преобразовать 8-битную строку в Юникод - путем добавления к ней пустой строки Юникода или с помощью функцииunicode()
:import timeit timer1 = timeit.Timer('unicode("abc")') timer2 = timeit.Timer('"abc" + u""') # Run three trials print timer1.repeat(repeat=3, number=100000) print timer2.repeat(repeat=3, number=100000) # On my laptop this outputs: # [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): ... """Dictionary lookalike implemented with lists.""" ... 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) # See that other dictionary methods are implemented ['__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']
(При участии Раймонда Хеттингера.)
Реализация DOM в
xml.dom.minidom
теперь может генерировать вывод XML в определенной кодировке, предоставляя необязательный аргумент кодировки методамtoxml()
иtoprettyxml()
узлов DOM.Модуль
xmlrpclib
теперь поддерживает расширение XML-RPC для работы с нулевыми значениями данных, такими как PythonNone
. Значения nil всегда поддерживаются при разгруппировке ответа XML-RPC. Чтобы генерировать запросы, содержащиеNone
, вы должны указать значение true для параметра allow_none при создании экземпляраMarshaller
.Новый модуль
DocXMLRPCServer
позволяет писать самодокументирующиеся XML-RPC серверы. Запустите его в демонстрационном режиме (как программу), чтобы увидеть его в действии. Указание веб-браузера на сервер RPC создает документацию в стиле pydoc; указание xmlrpclib на сервер позволяет вызывать фактические методы. (Внесено Брайаном Куинланом.)Добавлена поддержка интернационализированных доменных имен (RFCs 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
поддерживает Unicode URL с именами хостов, отличными от ASCII, при условии, чтоpath
часть URL только ASCII.Для реализации этого изменения были добавлены модуль
stringprep
, инструментmkstringprep
и кодировкаpunycode
.
Дата/время Тип¶
Типы даты и времени, подходящие для выражения временных меток, были добавлены в модуль datetime
. Эти типы не поддерживают различные календари или множество причудливых функций, а просто придерживаются основ представления времени.
Тремя основными типами являются: date
, представляющий день, месяц и год; time
, состоящий из часа, минуты и секунды; и datetime
, который содержит все атрибуты date
и time
. Существует также класс timedelta
, представляющий разницу между двумя точками во времени, а логика часовых поясов реализуется классами, наследующими от абстрактного класса tzinfo
.
Вы можете создавать экземпляры date
и time
, либо предоставляя аргументы в виде ключевых слов соответствующему конструктору, например datetime.date(year=1972, month=10, day=15)
, либо используя один из ряда методов класса. Например, метод класса date.today()
возвращает текущую местную дату.
После создания все экземпляры классов даты/времени являются неизменяемыми. Существует ряд методов для получения форматированных строк из объектов:
>>> import datetime
>>> now = datetime.datetime.now()
>>> now.isoformat()
'2002-12-30T21:27:03.994956'
>>> now.ctime() # Only available on 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
.
Для получения дополнительной информации обратитесь к справочной документации модуля. (Внесено Тимом Питерсом.)
Модуль optparse¶
Модуль 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 был написан Грегом Уордом с учетом предложений читателей Getopt SIG.
Pymalloc: Специализированный аллокатор объектов¶
Pymalloc, специализированный распределитель объектов, написанный Владимиром Марангозовым, был функцией, добавленной в Python 2.1. Pymalloc предназначен для того, чтобы быть быстрее системного malloc()
и иметь меньшие накладные расходы памяти для шаблонов выделения, типичных для программ Python. Распределитель использует функцию Си 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 используйте семейство «object»
PyObject_New()
,PyObject_NewVar()
иPyObject_Del()
.
Благодаря большой работе Тима Питерса, 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.
Изменения в API Build и C¶
Изменения в процессе сборки Python и в C API включают:
Реализация обнаружения циклов, используемая сборщиком мусора, оказалась стабильной, поэтому теперь она стала обязательной. Вы больше не можете компилировать Python без него, а переключатель
--with-cycle-gc
на configure был удален.Теперь Python можно собирать как разделяемую библиотеку (
libpython2.3.so
), указав--enable-shared
при запуске скрипта Python configure. (Внесено Ондреем Палковским.)Макросы
DL_EXPORT
иDL_IMPORT
теперь устарели. Функции инициализации для модулей расширения Python теперь должны объявляться с помощью нового макросаPyMODINIT_FUNC
, в то время как ядро Python обычно использует макросыPyAPI_FUNC
иPyAPI_DATA
.Интерпретатор можно скомпилировать без документаций для встроенных функций и модулей, добавив
--without-doc-strings
в сценарий configure. Это сделает исполняемый файл Python примерно на 10% меньше, но это также будет означать, что вы не сможете получить помощь по встроенным модулям Python. (Внесено Густаво Нимейером.)Макрос
PyArg_NoArgs()
теперь устарел, и код, использующий его, должен быть изменен. Для Python 2.2 и более поздних версий в таблице определения метода можно указать флагMETH_NOARGS
, сигнализирующий об отсутствии аргументов, и тогда проверка аргументов может быть удалена. Если важна совместимость с версиями Python до 2.2, код может использоватьPyArg_ParseTuple(args, "")
вместо этого, но это будет медленнее, чем использование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 или исходный текст.
Изменения, относящиеся к конкретному порту¶
Поддержка переноса на OS/2 от IBM с использованием среды выполнения EMX была включена в основное дерево исходных текстов Python. EMX - это слой эмуляции POSIX над системными API OS/2. Порт Python для EMX пытается поддерживать все POSIX-подобные возможности, предоставляемые средой выполнения EMX, и в основном преуспевает в этом; fork()
и fcntl()
ограничены ограничениями базового слоя эмуляции. Стандартный порт OS/2, использующий компилятор Visual Age от IBM, также получил поддержку семантики импорта, чувствительной к регистру, как часть интеграции порта EMX в CVS. (При участии Эндрю Макинтайра.)
В операционной системе MacOS большинство модулей инструментария были соединены слабыми ссылками для улучшения обратной совместимости. Это означает, что модули больше не будут не загружаться, если в текущей версии ОС отсутствует одна процедура. Вместо этого вызов отсутствующей процедуры вызовет исключение. (Внесено Джеком Янсеном.)
Файлы спецификаций RPM, находящиеся в каталоге Misc/RPM/
в исходном дистрибутиве Python, были обновлены для версии 2.3. (Внесено Шоном Рейфшнайдером).
Другие новые платформы, поддерживаемые Python, включают AtheOS (http://www.atheos.cx/), GNU/Hurd и OpenVMS.
Другие изменения и исправления¶
Как обычно, по всему дереву исходников разбросано множество других улучшений и исправлений. Поиск по журналам изменений 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
объектов frame, должны вместо этого вызыватьPyCode_Addr2Line(f->f_code, f->f_lasti)
. Это даст дополнительный эффект и заставит код работать так, как нужно при команде «python -O» в более ранних версиях Python.Замечательная новая возможность заключается в том, что функции трассировки теперь могут присваивать атрибут
f_lineno
объектам фрейма, изменяя строку, которая будет выполнена следующей. В отладчикjump
была добавлена командаpdb
, использующая преимущества этой новой возможности. (Реализовано Ричи Хиндлом.)
Перенос на Python 2.3¶
В этом разделе перечислены ранее описанные изменения, которые могут потребовать внесения изменений в ваш код:
yield
теперь всегда является ключевым словом; если оно используется как имя переменной в вашем коде, необходимо выбрать другое имя.Для строк X и Y,
X in Y
теперь работает, если длина X больше одного символа.Конструктор типа
int()
теперь будет возвращать длинное целое число вместо того, чтобы выдавать ошибку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)
.Вы больше не можете отключить утверждения, присвоив им значение
__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, теперь содержат модуль и символ
'.'
перед именем типа.
Благодарности¶
Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь в работе над различными черновиками этой статьи: Джефф Бауэр, Саймон Брюнинг, Бретт Кэннон, Майкл Чермсайд, Эндрю Далке, Скотт Дэвид Дэниелс, Фред Л. Дрейк, мл, Дэвид Фрейзер, Келли Гербер, Раймонд Хеттингер, Майкл Хадсон, Крис Ламберт, Детлеф Ланнерт, Мартин фон Лёвис, Эндрю Макинтайр, Лало Мартинс, Чад Нетцер, Густаво Нимейер, Нил Норвиц, Ханс Новак, Крис Риди, Франческо Риччарди, Винай Саджип, Нил Шеменауэр, Роман Сузи, Джейсон Тишлер, Юст ван Россум.