Что нового в 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, дата/время, возможность импорта модулей из архивов формата 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://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()
возвращает индексы, по которым найдена подстрока «или»: 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 это будет синтаксической ошибкой.
Объявление кодировки влияет только на литералы строк Юникода, которые будут преобразованы в Юникод с помощью указанной кодировки. Обратите внимание, что идентификаторы 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()
передается строка Юникода, Python теперь возвращает список строк Юникода. Новая функция os.getcwdu()
возвращает текущий каталог в виде строки Unicode.
Строки байтов по-прежнему работают как имена файлов, а в Windows Python прозрачно преобразует их в Юникод, используя кодировку mbcs
.
Другие системы также допускают использование строк Юникода в качестве имен файлов, но перед передачей в систему преобразуют их в байтовые строки, что может привести к возникновению ошибки UnicodeError
. Приложения могут проверить, поддерживаются ли произвольные строки Юникода в качестве имен файлов, проверив 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
при запуске скрипта configure Python.
См.также
- 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()
, которая записывает последний откат. Любая из других функций также запишет откат, если вы укажете значение true для ключевого слова-аргумента 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 были добавлены не ради строгой проверки типов. Очень строгий язык, такой как Pascal, также не позволил бы вам выполнять арифметику с булевыми числами и потребовал бы, чтобы выражение в операторе if
всегда приводило к булевому результату. Python не так строг и никогда не будет таким, о чем прямо говорит PEP 285. Это означает, что вы можете использовать любое выражение в операторе if
, даже то, которое оценивается как список, кортеж или какой-то случайный объект. Тип Boolean является подклассом класса int
, так что арифметика с использованием Boolean по-прежнему работает.
>>> 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 позволял задавать обработку ошибок как «strict» (повышение UnicodeError
), «ignore» (пропуск символа) или «replace» (использование вопросительного знака в выходной строке), причем «strict» используется по умолчанию. Может оказаться желательным указать альтернативные способы обработки таких ошибок, например, вставка ссылки на символ 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 - API для работы с файлами CSV
Авторы и исполнители: Кевин Алтис, Дэйв Коул, Эндрю Макнамара, Скип Монтанаро, Клифф Уэллс.
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]
Или используйте объекты slice непосредственно в субскриптах:
>>> 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 или прочитайте тему на 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(n2), требуемый для школьного алгоритма умножения. (Оригинальный патч Кристофера А. Крейга, значительно переработанный Тимом Питерсом).
Опкод
SET_LINENO
теперь отсутствует. Это может дать небольшой прирост скорости, в зависимости от особенностей вашего компилятора. Более подробное объяснение см. в разделе Другие изменения и исправления. (Удалено Майклом Хадсоном).Объекты
xrange()
теперь имеют собственный итератор, что делаетfor i in xrange(n)
немного быстрее, чемfor i in range(n)
. (Исправление от Raymond Hettinger.)В различных местах были сделаны небольшие перестановки для повышения производительности, например, вставка функций или удаление некоторого кода. (Реализовано в основном 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(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]
(Предоставлено Кевином О’Коннором.)
Интегрированная среда разработки IDLE была обновлена с использованием кода из проекта IDLEfork (https://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
включит буферизацию.В модуль
random
была добавлена функцияsample(population, k)
. 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. Для некоторых интерфейсов TclTkinter
теперь автоматически предотвращает это, когда к виджету обращаются из другого потока, маршаллируя команду, передавая ее в нужный поток и ожидая результатов. Другие интерфейсы не могут быть обработаны автоматически, но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-вывод в определенной кодировке, предоставляя необязательный аргумент encoding методамtoxml()
иtoprettyxml()
узлов DOM.Модуль
xmlrpclib
теперь поддерживает расширение XML-RPC для работы с нулевыми значениями данных, такими какNone
в Python. Нулевые значения всегда поддерживаются при разгруппировке ответа 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
поддерживает юникодные 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)
, либо используя один из ряда методов класса. Например, метод класса 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.
Изменения в сборке и C API¶
Изменения в процессе сборки Python и в C API включают:
Реализация обнаружения циклов, используемая сборщиком мусора, доказала свою стабильность, поэтому теперь она стала обязательной. Вы больше не сможете скомпилировать Python без нее, а переключатель
--with-cycle-gc
на configure был удален.Теперь Python можно собирать как разделяемую библиотеку (
libpython2.3.so
), указав--enable-shared
при запуске configure скрипта Python. (Внесено Ондреем Палковским.)Макросы
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 теперь входит копия исходного кода XML-парсера Expat, что устраняет зависимость от системной версии или локальной установки 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
объектов фрейма, должны вместо этого вызыватьPyCode_Addr2Line(f->f_code, f->f_lasti)
. Это даст дополнительный эффект - код будет работать так, как нужно при выполнении команды «python -O» в ранних версиях Python.Новая интересная возможность - функции трассировки теперь могут присваивать атрибут
f_lineno
объектам фрейма, изменяя строку, которая будет выполнена следующей. В отладчикpdb
была добавлена командаjump
, использующая эту новую возможность. (Реализовано Ричи Хиндлом).
Переход на Python 2.3¶
В этом разделе перечислены ранее описанные изменения, которые могут потребовать внесения изменений в ваш код:
yield
теперь всегда является ключевым словом; если оно используется в качестве имени переменной в вашем коде, необходимо выбрать другое имя.Для строк X и Y
X in Y
теперь работает, если X имеет длину более одного символа.Конструктор типа
int()
теперь возвращает длинное целое число, а не выдает ошибкуOverflowError
, когда строка или число с плавающей точкой слишком велико, чтобы поместиться в целое число.Если у вас есть строки Юникода, содержащие 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, теперь содержат модуль и символ
'.'
перед именем типа.
Благодарности¶
Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь в работе над различными черновиками этой статьи: Джефф Бауэр, Саймон Брюнинг, Бретт Кэннон, Майкл Чермсайд, Эндрю Далк, Скотт Дэвид Дэниелс, Фред Л. Дрейк-младший, Дэвид Фрейзер, Келли Гербер, Рэймонд Хеттингер, Майкл Хадсон, Крис Ламберт, Крис Хеттингер и др, Дэвид Фрейзер, Келли Гербер, Раймонд Хеттингер, Майкл Хадсон, Крис Ламберт, Детлеф Ланнерт, Мартин фон Лёвис, Эндрю Макинтайр, Лало Мартинс, Чад Нетцер, Густаво Нимейер, Нил Норвиц, Ханс Новак, Крис Риди, Франческо Риччарди, Винай Саджип, Нил Шеменауэр, Роман Сузи, Джейсон Тишлер, Джаст ван Россум.