Що нового в Python 2.5¶
- Автор
A.M. Kuchling
This article explains the new features in Python 2.5. The final release of Python 2.5 is scheduled for August 2006; PEP 356 describes the planned release schedule.
The changes in Python 2.5 are an interesting mix of language and library
improvements. The library enhancements will be more important to Python’s user
community, I think, because several widely-useful packages were added. New
modules include ElementTree for XML processing (xml.etree
),
the SQLite database module (sqlite
), and the ctypes
module for calling C functions.
Мовні зміни мають середнє значення. Було додано кілька приємних нових функцій, але більшість із них не є функціями, якими ви будете користуватися щодня. Умовні вирази нарешті були додані до мови за допомогою нового синтаксису; див. розділ PEP 308: Умовні вирази. Новий оператор „with
“ полегшить написання коду очищення (розділ PEP 343: оператор «з».). Тепер значення можна передавати в генератори (розділ PEP 342: Нові функції генератора). Імпорт тепер відображається як абсолютний або відносний (розділ PEP 328: Абсолютний і відносний імпорт). Деякі кутові випадки обробки винятків обробляються краще (розділ PEP 341: Уніфікована спроба/окрім/нарешті). Усі ці вдосконалення варті уваги, але це вдосконалення тієї чи іншої функції мови; жодна з них не є широкою модифікацією семантики Python.
Окрім мовних і бібліотечних доповнень, у всьому дереві вихідних кодів було зроблено інші покращення та виправлення помилок. Пошук у журналах змін SVN виявив, що між Python 2.4 і 2.5 було застосовано 353 виправлення та 458 виправлених помилок. (Обидві цифри, ймовірно, занижені.)
Ця стаття не намагається бути повною специфікацією нових функцій; натомість зміни коротко представлені з використанням корисних прикладів. Щоб отримати повну інформацію, завжди звертайтеся до документації для Python 2.5 на https://docs.python.org. Якщо ви хочете зрозуміти повну реалізацію та обґрунтування дизайну, зверніться до PEP для конкретної нової функції.
Коментарі, пропозиції та звіти про помилки щодо цього документа вітаються; будь ласка, надішліть їх електронною поштою автору або відкрийте помилку в системі відстеження помилок Python.
PEP 308: Умовні вирази¶
Протягом тривалого часу люди запитували спосіб написання умовних виразів, які є виразами, які повертають значення A або значення B залежно від того, чи є логічне значення true або false. Умовний вираз дає змогу написати один оператор присвоєння, який має той самий ефект, що й наступний:
if condition:
x = true_value
else:
x = false_value
Були нескінченні нудні дискусії щодо синтаксису як на python-dev, так і на comp.lang.python. Навіть було проведено голосування, яке виявило, що більшість виборців бажали використовувати умовні вирази в тій чи іншій формі, але не було жодного синтаксису, якому віддала б перевагу явна більшість. Серед кандидатів C cond ? true_v : false_v
, if cond then true_v else false_v
та 16 інших варіантів.
Зрештою Гвідо ван Россум обрав дивовижний синтаксис:
x = true_value if condition else false_value
Обчислення, як і в існуючих булевих виразах, все ще є ледачим, тому порядок обчислення трохи змінюється. Вираз умова в середині обчислюється спочатку, а вираз істинне_значення обчислюється, лише якщо умова була істинною. Подібним чином вираз false_value обчислюється лише тоді, коли умова false.
Цей синтаксис може здатися дивним і зворотним; чому умова стоїть у середині виразу, а не в передній частині, як у C c ? x : y
? Рішення було перевірено шляхом застосування нового синтаксису до модулів у стандартній бібліотеці та перегляду того, як читається отриманий код. У багатьох випадках, коли використовується умовний вираз, одне значення здається «звичайним випадком», а одне — «винятковим випадком», яке використовується лише в рідкісних випадках, коли умова не виконується. Умовний синтаксис робить цей шаблон трохи очевиднішим:
contents = ((doc + '\n') if doc else '')
Я прочитав наведене вище твердження як значення «тут contents зазвичай присвоюється значення doc+'\n'
; іноді doc є порожнім, у цьому особливому випадку повертається порожній рядок». Я сумніваюся, що буду дуже часто використовувати умовні вирази, де немає чіткого загального та незвичайного випадків.
Була деяка дискусія щодо того, чи повинна мова вимагати оточувати умовні вирази дужками. Було прийнято рішення не вимагати дужок у граматиці мови Python, але з точки зору стилю я вважаю, що ви повинні завжди використовувати їх. Розглянемо ці два твердження:
# First version -- no parens
level = 1 if logging else 0
# Second version -- with parens
level = (1 if logging else 0)
Я вважаю, що в першій версії око читача може згрупувати оператор у «level = 1», «if logging», «else 0» і вважати, що умова вирішує, чи виконується призначення level. Друга версія, на мій погляд, читається краще, оскільки в ній чітко видно, що призначення завжди виконується, а вибір здійснюється між двома значеннями.
Ще одна причина включення дужок: кілька дивних комбінацій списків і лямбда-виразів можуть виглядати як неправильні умовні вирази. Перегляньте PEP 308 для деяких прикладів. Якщо ви поставите круглі дужки навколо своїх умовних виразів, ви не зіткнетеся з цим випадком.
Дивись також
- PEP 308 - Умовні вирази
PEP, написаний Гвідо ван Россумом і Раймондом Д. Хеттінгером; реалізований Томасом Воутерсом.
PEP 309: Застосування часткової функції¶
Модуль functools
містить інструменти для програмування у функціональному стилі.
Одним з корисних інструментів у цьому модулі є функція partial()
. Для програм, написаних у функціональному стилі, ви іноді захочете побудувати варіанти існуючих функцій із заповненими деякими параметрами. Розглянемо функцію Python f(a, b, c)
; ви можете створити нову функцію g(b, c)
, яка була б еквівалентною f(1, b, c)
. Це називається «часткове застосування функції».
partial()
приймає аргументи (function, arg1, arg2, ... kwarg1=value1, kwarg2=value2)
. Отриманий об’єкт можна викликати, тому ви можете просто викликати його, щоб викликати функцію із заповненими аргументами.
Ось маленький, але реалістичний приклад:
import functools
def log (message, subsystem):
"Write the contents of 'message' to the specified subsystem."
print '%s: %s' % (subsystem, message)
...
server_log = functools.partial(log, subsystem='server')
server_log('Unable to open socket')
Ось ще один приклад із програми, яка використовує PyGTK. Тут динамічно створюється контекстно-залежне спливаюче меню. Зворотний виклик, наданий для опції меню, є частково застосованою версією методу open_item()
, де надано перший аргумент.
...
class Application:
def open_item(self, path):
...
def init (self):
open_func = functools.partial(self.open_item, item_path)
popup_menu.append( ("Open", open_func, 1) )
Іншою функцією в модулі functools
є функція update_wrapper(wrapper, wrapped)
, яка допомагає вам писати добре поведені декоратори. update_wrapper()
копіює ім’я, модуль і атрибут рядка документів у функцію-огортку, щоб легше було зрозуміти відстеження всередині обгорнутої функції. Наприклад, ви можете написати:
def my_decorator(f):
def wrapper(*args, **kwds):
print 'Calling decorated function'
return f(*args, **kwds)
functools.update_wrapper(wrapper, f)
return wrapper
wraps()
— це декоратор, який можна використовувати у ваших власних декораторах для копіювання інформації обгорнутої функції. Альтернативною версією попереднього прикладу буде:
def my_decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwds):
print 'Calling decorated function'
return f(*args, **kwds)
return wrapper
Дивись також
- PEP 309 - Застосування часткової функції
PEP запропонований і написаний Пітером Гаррісом; реалізований Хе-Шік Чангом і Ніком Когланом, з адаптацією Реймонда Геттінгера.
PEP 314: Метадані для програмних пакетів Python v1.1¶
У Distutils додано підтримку простих залежностей. Функція setup()
тепер має ключові параметри requires
, provides
і obsoletes
. Коли ви створюєте вихідний дистрибутив за допомогою команди sdist
, інформація про залежності буде записана у файл PKG-INFO
.
Іншим новим параметром ключового слова є download_url
, який має бути встановлено на URL-адресу вихідного коду пакета. Це означає, що тепер можна шукати запис в індексі пакетів, визначати залежності для пакета та завантажувати необхідні пакети.
VERSION = '1.0'
setup(name='PyPackage',
version=VERSION,
requires=['numarray', 'zlib (>=1.1.4)'],
obsoletes=['OldPackage']
download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
% VERSION),
)
Інше нове вдосконалення індексу пакетів Python на https://pypi.org — це зберігання вихідних і двійкових архівів для пакета. Нова команда upload Distutils завантажить пакет до репозиторію.
Перш ніж можна буде завантажити пакет, ви повинні мати можливість створити дистрибутив за допомогою команди sdist Distutils. Коли це запрацює, ви можете запустити python setup.py upload
, щоб додати свій пакет до архіву PyPI. За бажанням ви можете підписати пакет GPG, вказавши параметри --sign
і --identity
.
Завантаження пакетів було реалізовано Мартіном фон Льовісом і Річардом Джонсом.
Дивись також
- PEP 314 - метадані для програмних пакетів Python v1.1
PEP запропонований і написаний А.М. Кухлінг, Річард Джонс і Фред Дрейк; реалізований Річардом Джонсом і Фредом Дрейком.
PEP 328: Абсолютний і відносний імпорт¶
Простіша частина PEP 328 була реалізована в Python 2.4: тепер можна використовувати дужки для включення імен, імпортованих із модуля за допомогою оператора from ... import ...
, що полегшує імпорт багато різних імен.
Більш складна частина була реалізована в Python 2.5: для імпорту модуля можна вказати використання абсолютного або відносного імпорту пакетів. План полягає в тому, щоб у майбутніх версіях Python зробити абсолютний імпорт типовим.
Скажімо, у вас є такий каталог пакетів:
pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py
Це визначає пакет під назвою pkg
, що містить підмодулі pkg.main
і pkg.string
.
Розглянемо код у модулі main.py
. Що станеться, якщо він виконає оператор import string
? У Python 2.4 і раніших версіях він спочатку шукає каталог пакета, щоб виконати відносний імпорт, знаходить pkg/string.py
, імпортує вміст цього файлу як модуль pkg.string
, і цей модуль прив’язаний до імені string
у просторі імен модуля pkg.main
.
Це добре, якщо pkg.string
був тим, що ви хотіли. Але що, якщо вам потрібен стандартний модуль Python string
? Немає чистого способу ігнорувати pkg.string
і шукати стандартний модуль; загалом вам доводилося дивитися на вміст sys.modules
, який є трохи нечистим. Пакунок Хольгера Крекеля py.std
забезпечує більш акуратний спосіб виконання імпорту зі стандартної бібліотеки, import py; py.std.string.join()
, але цей пакет доступний не для всіх установок Python.
Читання коду, який покладається на відносний імпорт, також менш зрозуміле, тому що читач може заплутатися щодо того, який модуль, string
або pkg.string
, призначений для використання. Користувачі Python незабаром навчилися не дублювати назви модулів стандартної бібліотеки в назвах підмодулів своїх пакунків, але ви не можете захиститися від використання назви вашого підмодуля для нового модуля, доданого в майбутній версії Python.
У Python 2.5 ви можете змінити поведінку import
на абсолютний імпорт за допомогою директиви from __future__ import absolute_import
. Ця поведінка абсолютного імпорту стане типовою в майбутніх версіях (ймовірно, Python 2.7). Якщо абсолютний імпорт встановлено за замовчуванням, import string
завжди знаходитиме версію стандартної бібліотеки. Рекомендується, щоб користувачі якомога частіше використовували абсолютний імпорт, тому краще починати писати from pkg import string
у вашому коді.
Відносний імпорт все ще можливий, додавши початкову крапку до імені модуля під час використання форми from ... import
:
# Import names from pkg.string
from .string import name1, name2
# Import pkg.string
from . import string
Це імпортує модуль string
відносно поточного пакета, тому в pkg.main
буде імпортовано name1 і name2 з pkg.string
. Додаткові початкові періоди виконують відносний імпорт, починаючи з батьківського пакета поточного пакета. Наприклад, код у модулі A.B.C
може робити:
from . import D # Imports A.B.D
from .. import E # Imports A.E
from ..F import G # Imports A.F.G
Початкові крапки не можна використовувати з формою import modname
оператора імпорту, лише з формою from ... import
.
Дивись також
- PEP 328 - Імпорт: багаторядковий і абсолютний/відносний
PEP, написаний Aahz; реалізований Томасом Воутерсом.
- https://pylib.readthedocs.io/
Бібліотека py Хольгера Крекеля, яка містить пакет
py.std
.
PEP 338: Виконання модулів як сценаріїв¶
Перемикач -m
, доданий у Python 2.4 для виконання модуля як сценарію, отримав кілька додаткових можливостей. Замість того, щоб бути реалізованим у коді C всередині інтерпретатора Python, комутатор тепер використовує реалізацію в новому модулі, runpy
.
Модуль runpy
реалізує більш досконалий механізм імпорту, тому тепер можна запускати модулі в пакеті, наприклад pychecker.checker
. Модуль також підтримує альтернативні механізми імпорту, такі як модуль zipimport
. Це означає, що ви можете додати шлях архіву .zip до sys.path
, а потім використовувати перемикач -m
для виконання коду з архіву.
Дивись також
- PEP 338 - Виконання модулів у вигляді скриптів
PEP написав і реалізував Нік Коглан.
PEP 341: Уніфікована спроба/окрім/нарешті¶
До Python 2.5 оператор try
був у двох варіантах. Ви можете використовувати блок finally
, щоб гарантувати, що код завжди виконується, або один чи більше блоків except
, щоб перехоплювати певні винятки. Ви не могли поєднати обидва блоки except
і блок finally
, оскільки генерація правильного байт-коду для комбінованої версії була складною, і було незрозуміло, якою має бути семантика комбінованого оператора бути.
Гвідо ван Россум провів деякий час, працюючи з Java, яка підтримує еквівалент поєднання блоків except
і блоку finally
, і це прояснило, що має означати цей оператор. У Python 2.5 тепер можна писати:
try:
block-1 ...
except Exception1:
handler-1 ...
except Exception2:
handler-2 ...
else:
else-block
finally:
final-block
Код у block-1 виконується. Якщо код викликає виняток, перевіряються різні блоки except
: якщо виняток належить до класу Exception1
, виконується handler-1; інакше, якщо він належить до класу Exception2
, виконується обробник-2 і так далі. Якщо жодного винятку не виникає, виконується else-block.
Незалежно від того, що сталося раніше, final-block виконується після завершення блоку коду та обробки будь-яких викликаних винятків. Навіть якщо сталася помилка в обробнику винятків або else-block і виникає новий виняток, код у final-block все одно виконується.
Дивись також
- PEP 341 - Уніфікація try-except і try-finally
PEP, написаний Георгом Брандлом; виконання Томаса Лі.
PEP 342: Нові функції генератора¶
Python 2.5 додає простий спосіб передачі значень у генератор. Як було введено в Python 2.3, генератори створюють лише вихід; як тільки код генератора був викликаний для створення ітератора, не було можливості передати будь-яку нову інформацію у функцію, коли її виконання відновилося. Іноді можливість передати певну інформацію буде корисною. Хакерські рішення для цього включають змусити код генератора переглядати глобальну змінну, а потім змінювати значення глобальної змінної або передавати якийсь змінний об’єкт, який потім змінюють абоненти.
Щоб оновити вашу пам’ять про основні генератори, ось простий приклад:
def counter (maximum):
i = 0
while i < maximum:
yield i
i += 1
Коли ви викликаєте counter(10)
, результатом є ітератор, який повертає значення від 0 до 9. Коли зустрічається оператор yield
, ітератор повертає надане значення та призупиняє виконання функції, збереження локальних змінних. Виконання поновлюється після наступного виклику методу next()
ітератора, який починається після оператора yield
.
У Python 2.3 yield
був оператором; він не повернув жодного значення. У версії 2.5 yield
тепер є виразом, що повертає значення, яке можна призначити змінній або іншим чином оперувати:
val = (yield i)
Я рекомендую вам завжди брати дужки навколо виразу yield
, коли ви щось робите з повернутим значенням, як у прикладі вище. Дужки не завжди потрібні, але простіше завжди додавати їх замість того, щоб запам’ятовувати, коли вони потрібні.
(PEP 342 пояснює точні правила, які полягають у тому, що yield
-вираз завжди повинен бути взятий у дужки, за винятком випадків, коли він зустрічається у виразі верхнього рівня в правій частині призначення. Це означає, що ви можете написати val = yield i
, але повинні використовувати круглі дужки, коли є операція, як у val = (yield i) + 12
.)
Значення надсилаються в генератор шляхом виклику його методу send(value)
. Потім код генератора відновлюється, і вираз yield
повертає вказане значення. Якщо викликається звичайний метод next()
, yield
повертає None
.
Ось попередній приклад, змінений, щоб дозволити змінювати значення внутрішнього лічильника.
def counter (maximum):
i = 0
while i < maximum:
val = (yield i)
# If value provided, change counter
if val is not None:
i = val
else:
i += 1
А ось приклад зміни лічильника:
>>> it = counter(10)
>>> print it.next()
0
>>> print it.next()
1
>>> print it.send(8)
8
>>> print it.next()
9
>>> print it.next()
Traceback (most recent call last):
File "t.py", line 15, in ?
print it.next()
StopIteration
yield
зазвичай повертає None
, тому ви завжди повинні перевіряти цей випадок. Не просто використовуйте його значення у виразах, якщо ви не впевнені, що метод send()
буде єдиним методом, використаним для відновлення вашої функції генератора.
Крім send()
, є ще два нові методи генераторів:
throw(type, value=None, traceback=None)
використовується для створення винятку всередині генератора; виняток викликає виразyield
, де виконання генератора призупинено.close()
створює новий винятокGeneratorExit
всередині генератора, щоб завершити ітерацію. Отримавши цей виняток, код генератора повинен викликатиGeneratorExit
абоStopIteration
. Перехоплення виняткуGeneratorExit
і повернення значення є незаконним і викличеRuntimeError
; якщо функція викликає якийсь інший виняток, цей виняток поширюється на виклик.close()
також буде викликано збирачем сміття Python, коли генератор збирає сміття.Якщо вам потрібно запустити код очищення, коли виникає
GeneratorExit
, я пропоную використовувати набірtry: ... finally:
замість перехопленняGeneratorExit
.
Кумулятивний ефект цих змін полягає в тому, щоб перетворити генераторів з односторонніх виробників інформації на виробників і споживачів.
Генератори також стають сопрограмами, більш узагальненою формою підпрограм. Підпрограми вводяться в одній точці та виходять з іншої точки (верхня частина функції та оператор return
), але до підпрограм можна ввійти, вийти з них і відновити їх у багатьох різних точках ( yield
заяви). Нам доведеться з’ясувати шаблони для ефективного використання співпрограм у Python.
Додавання методу close()
має один побічний ефект, який не є очевидним. close()
викликається, коли генератор збирає сміття, тому це означає, що код генератора отримує останній шанс запуститися, перш ніж генератор буде знищено. Цей останній шанс означає, що оператори try...finally
у генераторах тепер можуть гарантовано працювати; речення finally
тепер завжди матиме шанс запуститися. Синтаксичне обмеження, згідно з яким ви не можете змішувати оператори yield
із пакетом try...finally
, було видалено. Це виглядає як незначна мовна дрібниця, але використання генераторів і try...finally
насправді є необхідним для реалізації оператора with
, описаного PEP 343. Я розгляну цю нову заяву в наступному розділі.
Інший ще більш езотеричний ефект цієї зміни: раніше атрибут gi_frame
генератора завжди був об’єктом фрейму. Тепер gi_frame
може мати значення None
, коли генератор вичерпано.
Дивись також
- PEP 342 - Співпрограми через розширені генератори
PEP, написаний Гвідо ван Россумом і Філіпом Дж. Ебі; реалізовано Філіпом Дж. Ебі. Містить приклади більш химерного використання генераторів як співпрограм.
Попередні версії цих функцій були запропоновані в PEP 288 Реймондом Геттінгером і PEP 325 Самуелем Педроні.
- https://en.wikipedia.org/wiki/Coroutine
Запис у Вікіпедії для співпрограм.
- http://www.sidhe.org/~dan/blog/archives/000178.html
Пояснення співпрограм з точки зору Perl, написане Деном Сугальським.
PEP 343: оператор «з».¶
Інструкція „with
“ уточнює код, який раніше використовував блоки try...finally
, щоб забезпечити виконання коду очищення. У цьому розділі я обговорю твердження, як воно буде зазвичай використовуватися. У наступному розділі я розгляну деталі реалізації та покажу, як писати об’єкти для використання з цим оператором.
Оператор „with
“ — це нова структура потоку керування, основна структура якої:
with expression [as variable]:
with-block
Вираз обчислюється, і в результаті він має отримати об’єкт, який підтримує протокол керування контекстом (тобто має методи __enter__()
і __exit__()
.
__enter__()
об’єкта викликається перед виконанням with-block і тому може запускати код налаштування. Він також може повертати значення, яке прив’язане до імені змінної, якщо його задано. (Зверніть увагу, що змінній не присвоєно результат виразу.)
Після завершення виконання with-block викликається метод __exit__()
об’єкта, навіть якщо блок викликав виняткову ситуацію, і тому може запустити код очищення.
Щоб увімкнути оператор у Python 2.5, вам потрібно додати таку директиву до свого модуля:
from __future__ import with_statement
Оператор завжди буде ввімкнено в Python 2.6.
Деякі стандартні об’єкти Python тепер підтримують протокол керування контекстом і можуть використовуватися з оператором „with
“. Одним із прикладів є файлові об’єкти:
with open('/etc/passwd', 'r') as f:
for line in f:
print line
... more processing code ...
Після виконання цього оператора файловий об’єкт у f буде автоматично закрито, навіть якщо цикл for
викликав виняток під час проходження блоку.
Примітка
У цьому випадку f — це той самий об’єкт, створений open()
, оскільки file.__enter__()
повертає self.
Блокування та змінні умови модуля threading
також підтримують оператор „with
“:
lock = threading.Lock()
with lock:
# Critical section of code
...
Блокування встановлюється перед виконанням блоку та завжди знімається після завершення блоку.
Нова функція localcontext()
у модулі decimal
дозволяє легко зберігати та відновлювати поточний десятковий контекст, який інкапсулює бажану точність і характеристики округлення для обчислень:
from decimal import Decimal, Context, localcontext
# Displays with default precision of 28 digits
v = Decimal('578')
print v.sqrt()
with localcontext(Context(prec=16)):
# All code in this block uses a precision of 16 digits.
# The original context is restored on exiting the block.
print v.sqrt()
Написання менеджерів контексту¶
Під капотом оператор „with
“ досить складний. Більшість людей використовуватимуть „with
“ тільки в компанії з існуючими об’єктами, і їм не потрібно знати ці деталі, тому ви можете пропустити решту цього розділу, якщо хочете. Авторам нових об’єктів потрібно буде зрозуміти деталі базової реалізації та продовжувати читати.
Загальне пояснення протоколу керування контекстом таке:
Вираз обчислюється та має призвести до об’єкта, який називається «менеджер контексту». Менеджер контексту повинен мати методи
__enter__()
і__exit__()
.Викликається метод
__enter__()
контекстного менеджера. Повернуте значення присвоюється VAR. Якщо немає пропозиції'as VAR''
, значення просто відкидається.Код у BLOCK виконується.
Якщо BLOCK викликає виняток, викликається
__exit__(type, value, traceback)
з деталями винятку, ті самі значення, які повертаєsys.exc_info()
. Повернене значення методу контролює, чи буде виняток повторно викликаний: будь-яке значення false повторно викликає виняток, аTrue
призведе до його придушення. Ви рідко захочете придушити виняток, тому що, якщо ви це зробите, автор коду, що містить оператор „with
“, ніколи не зрозуміє, що щось пішло не так.Якщо BLOCK не викликає винятку, метод
__exit__()
все одно викликається, але type, value і traceback мають значенняNone
.
Давайте поміркуємо на прикладі. Я не буду представляти детальний код, а лише накидаю методи, необхідні для бази даних, яка підтримує транзакції.
(Для людей, які не знайомі з термінологією бази даних: набір змін до бази даних групується в транзакцію. Транзакції можуть бути або зафіксованими, тобто всі зміни записуються в базу даних, або відкоченими, тобто всі зміни скасовуються та база даних не змінена. Для отримання додаткової інформації зверніться до будь-якого підручника з баз даних.)
Припустімо, що існує об’єкт, що представляє з’єднання з базою даних. Нашою метою буде дозволити користувачеві писати такий код:
db_connection = DatabaseConnection()
with db_connection as cursor:
cursor.execute('insert into ...')
cursor.execute('delete from ...')
# ... more operations ...
Транзакцію слід зафіксувати, якщо код у блоці працює бездоганно, або відкотити, якщо є виняткова ситуація. Ось базовий інтерфейс для DatabaseConnection
, який я припускаю:
class DatabaseConnection:
# Database interface
def cursor (self):
"Returns a cursor object and starts a new transaction"
def commit (self):
"Commits current transaction"
def rollback (self):
"Rolls back current transaction"
Метод __enter__()
досить простий, вам потрібно лише почати нову транзакцію. Для цієї програми отриманий об’єкт курсора буде корисним результатом, тому метод поверне його. Потім користувач може додати as cursor
до свого оператора „with
“, щоб прив’язати курсор до імені змінної.
class DatabaseConnection:
...
def __enter__ (self):
# Code to start a new transaction
cursor = self.cursor()
return cursor
Метод __exit__()
є найскладнішим, тому що в ньому потрібно виконати більшу частину роботи. Метод повинен перевірити, чи сталася виняткова ситуація. Якщо не було винятку, транзакція зафіксована. Транзакція відкочується, якщо стався виняток.
У наведеному нижче коді виконання просто припиниться в кінці функції, повертаючи значення за замовчуванням None
. None
є хибним, тому виняток буде знову створено автоматично. Якщо ви бажаєте, ви можете бути більш чіткими та додати оператор return
у позначене місце.
class DatabaseConnection:
...
def __exit__ (self, type, value, tb):
if tb is None:
# No exception, so commit
self.commit()
else:
# Exception occurred, so rollback.
self.rollback()
# return False
Модуль contextlib¶
Новий модуль contextlib
надає деякі функції та декоратор, корисні для написання об’єктів для використання з оператором „with
“.
Декоратор називається contextmanager()
і дозволяє писати одну функцію-генератор замість визначення нового класу. Генератор повинен видавати рівно одне значення. Код до yield
буде виконано як метод __enter__()
, а отримане значення буде поверненим значенням методу, яке буде прив’язано до змінної в „with
„ оператора as
пункт, якщо такий є. Код після yield
буде виконано в методі __exit__()
. Будь-які винятки, викликані в блоці, будуть викликані оператором yield
.
Наш приклад бази даних із попереднього розділу можна записати за допомогою цього декоратора як:
from contextlib import contextmanager
@contextmanager
def db_transaction (connection):
cursor = connection.cursor()
try:
yield cursor
except:
connection.rollback()
raise
else:
connection.commit()
db = DatabaseConnection()
with db_transaction(db) as cursor:
...
Модуль contextlib
також має функцію nested(mgr1, mgr2, ...)
, яка об’єднує кілька контекстних менеджерів, тому вам не потрібно писати вкладений „with
“ заяви. У цьому прикладі один оператор „with
“ запускає транзакцію бази даних і отримує блокування потоку:
lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):
...
Нарешті, функція closing(object)
повертає object, щоб його можна було прив’язати до змінної, і викликає object.close
у кінці блоку.
import urllib, sys
from contextlib import closing
with closing(urllib.urlopen('http://www.yahoo.com')) as f:
for line in f:
sys.stdout.write(line)
Дивись також
- PEP 343 - оператор «з».
PEP, написаний Гвідо ван Россумом і Ніком Когланом; реалізований Майком Блендом, Гвідо ван Россумом і Нілом Норвітцем. PEP показує код, згенерований для оператора „
with
“, який може бути корисним для вивчення того, як працює оператор.
Документація для модуля contextlib
.
PEP 352: Винятки як класи нового стилю¶
Класи винятків тепер можуть бути класами нового стилю, а не лише класичними класами, а також вбудованим класом Exception
і всіма стандартними вбудованими винятками (NameError
, ValueError
, і т.д.) тепер є класами нового стилю.
Ієрархію успадкування для винятків було дещо змінено. У 2.5 відносини успадкування такі:
BaseException # New in Python 2.5
|- KeyboardInterrupt
|- SystemExit
|- Exception
|- (all other current built-in exceptions)
Це перевпорядкування було зроблено, оскільки люди часто хочуть перехопити всі винятки, які вказують на помилки програми. KeyboardInterrupt
і SystemExit
не є помилками, однак, і зазвичай представляють явну дію, наприклад натискання користувачем Control-C або виклик коду sys.exit()
. Голе except:
перехопить усі винятки, тому вам зазвичай потрібно перерахувати KeyboardInterrupt
і SystemExit
, щоб повторно викликати їх. Звичайний шаблон такий:
try:
...
except (KeyboardInterrupt, SystemExit):
raise
except:
# Log error...
# Continue running program...
У Python 2.5 тепер ви можете написати except Exception
, щоб досягти того самого результату, перехоплюючи всі винятки, які зазвичай вказують на помилки, але залишаючи KeyboardInterrupt
і SystemExit
окремо. Як і в попередніх версіях, голе except:
усе ще перехоплює всі винятки.
Мета для Python 3.0 полягає в тому, щоб вимагати, щоб будь-який клас, створений як виняток, походив від BaseException
або якогось нащадка BaseException
, і в майбутніх випусках серії Python 2.x це обмеження може почати застосовуватися. . Тому я пропоную вам почати робити всі ваші класи винятків похідними від Exception
зараз. Було запропоновано, що чисту форму except:
слід видалити в Python 3.0, але Гвідо ван Россум не вирішив, робити це чи ні.
Викликання рядків як винятків, як у виразі raise "Сталася помилка"
, застаріло в Python 2.5 і викличе попередження. Мета полягає в тому, щоб мати можливість видалити функцію виключення рядків у кількох випусках.
Дивись також
- PEP 352 - обов’язковий суперклас для винятків
PEP, написаний Бреттом Кенноном і Гвідо ван Россумом; реалізовано Бреттом Кенноном.
PEP 353: використання ssize_t як типу індексу¶
A wide-ranging change to Python’s C API, using a new Py_ssize_t
type
definition instead of int
, will permit the interpreter to handle more
data on 64-bit platforms. This change doesn’t affect Python’s capacity on 32-bit
platforms.
Various pieces of the Python interpreter used C’s int
type to store
sizes or counts; for example, the number of items in a list or tuple were stored
in an int
. The C compilers for most 64-bit platforms still define
int
as a 32-bit type, so that meant that lists could only hold up to
2**31 - 1
= 2147483647 items. (There are actually a few different
programming models that 64-bit C compilers can use – see
http://www.unix.org/version2/whatsnew/lp64_wp.html for a discussion – but the
most commonly available model leaves int
as 32 bits.)
Обмеження в 2147483647 елементів насправді не має значення на 32-розрядній платформі, тому що у вас закінчиться пам’ять, перш ніж досягнеться обмеження довжини. Кожен елемент списку потребує місця для вказівника, який становить 4 байти, плюс місце для PyObject
, що представляє елемент. 2147483647*4 — це вже більше байтів, ніж може вмістити 32-розрядний адресний простір.
It’s possible to address that much memory on a 64-bit platform, however. The
pointers for a list that size would only require 16 GiB of space, so it’s not
unreasonable that Python programmers might construct lists that large.
Therefore, the Python interpreter had to be changed to use some type other than
int
, and this will be a 64-bit type on 64-bit platforms. The change
will cause incompatibilities on 64-bit machines, so it was deemed worth making
the transition now, while the number of 64-bit users is still relatively small.
(In 5 or 10 years, we may all be on 64-bit machines, and the transition would
be more painful then.)
Ця зміна найбільше впливає на авторів модулів розширення C. Рядки Python і типи контейнерів, такі як списки та кортежі, тепер використовують Py_ssize_t
для зберігання свого розміру. Такі функції, як PyList_Size()
тепер повертають Py_ssize_t
. Тому в коді модулів розширення може знадобитися змінити деякі змінні на Py_ssize_t
.
The PyArg_ParseTuple()
and Py_BuildValue()
functions have a new
conversion code, n
, for Py_ssize_t
. PyArg_ParseTuple()
“s
s#
and t#
still output int
by default, but you can define the
macro PY_SSIZE_T_CLEAN
before including Python.h
to make
them return Py_ssize_t
.
PEP 353 містить розділ про вказівки щодо перетворення, який слід прочитати авторам розширень, щоб дізнатися про підтримку 64-розрядних платформ.
Дивись також
- PEP 353 - Використання ssize_t як типу індексу
PEP написаний і реалізований Мартіном фон Льовісом.
PEP 357: метод „__index__“¶
У розробників NumPy була проблема, яку можна було вирішити, лише додавши новий спеціальний метод __index__()
. При використанні нотації фрагментів, як у [start:stop:step]
, значення індексів start, stop і step мають бути цілими або довгими цілими числами. NumPy визначає різноманітність спеціалізованих типів цілих чисел, що відповідають цілим числам без знаку та знаку 8, 16, 32 та 64 біт, але не було жодного способу вказати, що ці типи можна використовувати як індекси зрізів.
Зрізання не може використовувати лише існуючий метод __int__()
, оскільки цей метод також використовується для реалізації приведення до цілих чисел. Якщо використати секцію __int__()
, числа з плаваючою комою також стануть законними індексами фрагментів, і це явно небажана поведінка.
Замість цього було додано новий спеціальний метод під назвою __index__()
. Він не приймає аргументів і повертає ціле число, що дає індекс фрагмента для використання. Наприклад:
class C:
def __index__ (self):
return self.value
Повернене значення має бути або цілим числом Python, або довгим цілим числом. Інтерпретатор перевірить, чи повернутий тип правильний, і викличе TypeError
, якщо ця вимога не виконується.
Відповідний слот nb_index
додано до структури рівня C PyNumberMethods
, щоб дозволити розширенням C реалізувати цей протокол. PyNumber_Index(obj)
можна використовувати в коді розширення для виклику функції __index__()
і отримання її результату.
Дивись також
- PEP 357 - Дозволяє використовувати будь-який об’єкт для нарізки
PEP написаний і реалізований Тревісом Оліфантом.
Інші зміни мови¶
Ось усі зміни, які Python 2.5 вносить у основну мову Python.
Тип
dict
має новий хук, який дозволяє підкласам надавати значення за замовчуванням, коли ключ не міститься в словнику. Якщо ключ не знайдено, буде викликано метод__missing__(key)
словника. Цей хук використовується для реалізації нового класуdefaultdict
в модуліcollections
. У наступному прикладі визначено словник, який повертає нуль для будь-якого відсутнього ключа:class zerodict (dict): def __missing__ (self, key): return 0 d = zerodict({1:1, 2:2}) print d[1], d[2] # Prints 1, 2 print d[3], d[4] # Prints 0, 0
І 8-бітні рядки, і рядки Unicode мають нові методи
partition(sep)
іrpartition(sep)
, які спрощують загальний варіант використання.Метод
find(S)
часто використовується для отримання індексу, який потім використовується для розрізання рядка та отримання частин, які знаходяться перед і після роздільника.partition(sep)
зводить цей шаблон до одного виклику методу, який повертає 3-кортеж, що містить підрядок перед роздільником, сам роздільник і підрядок після роздільника. Якщо роздільник не знайдено, перший елемент кортежу є цілим рядком, а інші два елементи порожні.rpartition(sep)
також повертає 3-кортеж, але починає пошук з кінця рядка;r
означає „зворотний“.Деякі приклади:
>>> ('http://www.python.org').partition('://') ('http', '://', 'www.python.org') >>> ('file:/usr/share/doc/index.html').partition('://') ('file:/usr/share/doc/index.html', '', '') >>> (u'Subject: a quick question').partition(':') (u'Subject', u':', u' a quick question') >>> 'www.python.org'.rpartition('.') ('www.python', '.', 'org') >>> 'www.python.org'.rpartition(':') ('', '', 'www.python.org')
(Реалізовано Фредріком Лундом за пропозицією Раймонда Геттінгера.)
Методи
startswith()
іendswith()
типів рядків тепер приймають кортежі рядків для перевірки.def is_image_file (filename): return filename.endswith(('.gif', '.jpg', '.tiff'))
(Реалізовано Георгом Брандлом за пропозицією Тома Лінна.)
Вбудовані функції
min()
іmax()
отримали параметр ключового словаkey
, аналогічний аргументуkey
дляsort()
. Цей параметр надає функцію, яка приймає один аргумент і викликається для кожного значення в списку;min()
/max()
поверне елемент із найменшим/найбільшим значенням, що повертається цією функцією. Наприклад, щоб знайти найдовший рядок у списку, ви можете зробити:L = ['medium', 'longest', 'short'] # Prints 'longest' print max(L, key=len) # Prints 'short', because lexicographically 'short' has the largest value print max(L)
(Надано Стівеном Бетардом і Реймондом Геттінгером.)
Дві нові вбудовані функції,
any()
іall()
, оцінюють, чи містить ітератор значення true або false.any()
повертаєTrue
, якщо будь-яке значення, яке повертає ітератор, є істинним; інакше він повернеFalse
.all()
повертаєTrue
тільки якщо всі значення, повернуті ітератором, оцінюються як істинні. (Запропоновано Гвідо ван Россумом і реалізовано Раймондом Геттінгером.)Результатом методу
__hash__()
класу тепер може бути або довге ціле, або звичайне ціле число. Якщо повертається довге ціле число, береться хеш цього значення. У попередніх версіях хеш-значення повинно було бути звичайним цілим числом, але у 2.5 вбудованийid()
було змінено, щоб завжди повертати невід’ємні числа, і користувачі часто використовуютьid(self)
в методах__hash__()
(хоча це не рекомендується).ASCII тепер є стандартним кодуванням для модулів. Тепер це синтаксична помилка, якщо модуль містить рядкові літерали з 8-бітовими символами, але не має оголошення кодування. У Python 2.4 це викликало попередження, а не синтаксичну помилку. Перегляньте PEP 263, щоб дізнатися, як оголосити кодування модуля; наприклад, ви можете додати такий рядок у верхній частині вихідного файлу:
# -*- coding: latin1 -*-
Нове попередження,
UnicodeWarning
, спрацьовує, коли ви намагаєтеся порівняти рядок Unicode з 8-бітним рядком, який не можна перетворити на Unicode за допомогою стандартного кодування ASCII. Результат порівняння false:>>> chr(128) == unichr(128) # Can't convert chr(128) to Unicode __main__:1: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal False >>> chr(127) == unichr(127) # chr(127) can be converted True
Раніше це викликало виняток
UnicodeDecodeError
, але у версії 2.5 це могло призвести до загадкових проблем під час доступу до словника. Якщо ви шукалиunichr(128)
іchr(128)
використовувався як ключ, ви отримали б винятокUnicodeDecodeError
. Інші зміни у 2.5 призвели до того, що цей виняток було викликано замість придушення кодом уdictobject.c
, який реалізує словники.Створення винятку для такого порівняння є абсолютно правильним, але зміна могла порушити код, тому замість цього було введено
UnicodeWarning
.(Реалізовано Марком-Андре Лембургом.)
Одна з помилок, яку інколи допускають програмісти на Python, полягає в тому, що вони забувають включити модуль
__init__.py
в каталог пакунків. Налагодження цієї помилки може заплутати, і зазвичай вимагає запуску Python з перемикачем-v
, щоб реєструвати всі шукані шляхи. У Python 2.5 нове попередженняImportWarning
спрацьовує, коли імпорт мав би отримати каталог як пакет, але не було знайдено__init__.py
. За замовчуванням це попередження мовчки ігнорується; надайте параметр-Wd
під час запуску виконуваного файлу Python для відображення попереджувального повідомлення. (Реалізовано Томасом Воутерсом.)Список базових класів у визначенні класу тепер може бути порожнім. Як приклад, це зараз законно:
class C(): pass
(Реалізовано Бреттом Кенноном.)
Зміни інтерактивного інтерпретатора¶
В інтерактивному інтерпретаторі quit
і exit
вже давно є рядками, тому нові користувачі отримують дещо корисне повідомлення, коли вони намагаються вийти:
>>> quit
'Use Ctrl-D (i.e. EOF) to exit.'
У Python 2.5 quit
і exit
тепер є об’єктами, які все ще створюють рядкові представлення самих себе, але також можуть викликатися. Новачки, які спробують quit()
або exit()
тепер вийдуть з інтерпретатора, як вони очікують. (Реалізовано Георгом Брандлом.)
Виконуваний файл Python тепер приймає стандартні довгі параметри --help
і --version
; у Windows він також приймає /?
параметр для відображення довідкового повідомлення. (Реалізовано Георгом Брандлом.)
Оптимізації¶
Декілька оптимізацій було розроблено під час спринту NeedForSpeed, заходу, який проходив у Рейк’явіку, Ісландія, 21–28 травня 2006 року. Спринт був зосереджений на підвищенні швидкості реалізації CPython і фінансувався EWT LLC за місцевої підтримки від CCP Games. Ці оптимізації, додані під час цього спринту, спеціально позначені в наступному списку.
Коли вони були представлені в Python 2.4, вбудовані типи
set
іfrozenset
були створені поверх типу словника Python. У 2.5 внутрішню структуру даних було налаштовано для реалізації наборів, і в результаті набори використовуватимуть на третину менше пам’яті та будуть дещо швидшими. (Реалізовано Раймондом Хеттінгером.)Швидкість деяких операцій Unicode, таких як пошук підрядків, поділ рядків і кодування та декодування карти символів, покращено. (Фредрік Лунд і Ендрю Далке під час спринту NeedForSpeed удосконалили пошук підрядків і розділення. Карти символів покращили Вальтер Дьорвальд і Мартін фон Льовіс.)
Функція long(str, base) тепер працює швидше з довгими рядками цифр, оскільки обчислюється менше проміжних результатів. Пік припадає на рядки приблизно з 800–1000 цифр, де функція працює в 6 разів швидше. (Надано Аланом Макінтайром і зроблено під час спринту NeedForSpeed.)
Тепер заборонено змішувати ітерацію по файлу з
для рядка у файлі
та викликом методівread()
/readline()
/readlines()
об’єкта файлу. Ітерація використовує внутрішній буфер, а методиread*()
не використовують цей буфер. Натомість вони повертатимуть дані після буфера, через що дані виглядатимуть не в порядку. Змішування ітерації та цих методів тепер ініціюєValueError
з методуread*()
. (Реалізовано Томасом Воутерсом.)Модуль
struct
тепер компілює рядки формату структури у внутрішнє представлення та кешує це представлення, що забезпечує 20% прискорення. (Надано Бобом Іполіто під час спринту NeedForSpeed.)Модуль
re
отримав прискорення на 1 або 2% завдяки переключенню на функції виділення Python замість системнихmalloc()
іfree()
. (Надано Джеком Дідеріхом під час спринту NeedForSpeed.)Оптимізатор peephole генератора коду тепер виконує просту постійну згортання виразів. Якщо ви напишете щось на кшталт
a = 2+3
, генератор коду виконає арифметику та створить код, що відповідаєa = 5
. (Запропоновано та реалізовано Раймондом Хеттінгером.)Виклики функцій тепер швидші, оскільки об’єкти коду тепер зберігають останній готовий кадр («зомбі-кадр») у внутрішньому полі об’єкта коду, повторно використовуючи його під час наступного виклику об’єкта коду. (Оригінальний патч Майкла Хадсона, модифікований Арміном Ріго та Річардом Джонсом; зроблено під час спринту NeedForSpeed.) Об’єкти фрейму також трохи менші, що може покращити локальність кешу та трохи зменшити використання пам’яті. (Надав Ніл Норвіц.)
Вбудовані винятки Python тепер є класами нового стилю, зміна, яка значно прискорює створення екземплярів. Тому обробка винятків у Python 2.5 приблизно на 30% швидша, ніж у 2.4. (Річард Джонс, Георг Брандл і Шон Райфшнайдер на спринті NeedForSpeed.)
Імпорт тепер кешує спробовані шляхи, записуючи їх існування чи ні, щоб інтерпретатор здійснював менше викликів
open()
іstat()
під час запуску. (Надано Мартіном фон Льовісом і Георгом Брандлом.)
Нові, покращені та видалені модулі¶
Стандартна бібліотека отримала багато вдосконалень і виправлень помилок у Python 2.5. Ось неповний список найбільш помітних змін, відсортованих за алфавітом назв модулів. Зверніться до файлу Misc/NEWS
у дереві вихідних кодів, щоб отримати більш повний список змін, або перегляньте журнали SVN, щоб отримати всі деталі.
Модуль
audioop
тепер підтримує кодування a-LAW, а код для кодування u-LAW було вдосконалено. (Надав Ларс Імміш.)Модуль
codecs
отримав підтримку інкрементних кодеків. Функціяcodec.lookup()
тепер повертає екземплярCodecInfo
замість кортежу. ЕкземпляриCodecInfo
поводяться як 4-кортеж, щоб зберегти зворотну сумісність, але також мають атрибутиencode
,decode
,incrementalencoder
,incrementaldecoder
,streamwriter
іstreamreader
. Інкрементні кодеки можуть отримувати вхідні дані та виводити їх кількома порціями; вихідний сигнал такий самий, як якби весь вхід був поданий до неінкрементного кодека. Подробиці дивіться в документації модуляcodecs
. (Розроблено та реалізовано Вальтером Дьорвальдом.)Модуль
collections
отримав новий тип,defaultdict
, який є підкласами стандартного типуdict
. Новий тип здебільшого веде себе як словник, але створює значення за замовчуванням, коли ключ відсутній, автоматично додаючи його до словника для запитуваного значення ключа.Першим аргументом конструктора
defaultdict
є фабрична функція, яка викликається щоразу, коли запитується ключ, але він не знайдений. Ця фабрична функція не отримує аргументів, тому ви можете використовувати вбудовані конструктори типу, такі якlist()
абоint()
. Наприклад, ви можете скласти покажчик слів на основі їх початкової літери так:words = """Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura che la diritta via era smarrita""".lower().split() index = defaultdict(list) for w in words: init_letter = w[0] index[init_letter].append(w)
Друк
index
призводить до наступного результату:defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'], 'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'], 'l': ['la'], 'o': ['oscura'], 'n': ['nel', 'nostra'], 'p': ['per'], 's': ['selva', 'smarrita'], 'r': ['ritrovai'], 'u': ['una'], 'v': ['vita', 'via']}
(Надав Гвідо ван Россум.)
Тип двосторонньої черги
deque
, наданий модулемcollections
, тепер має методremove(value)
, який видаляє перше входження value у черзі, викликаючиValueError
, якщо значення не знайдено. (Надав Реймонд Геттінгер.)Новий модуль: Модуль
contextlib
містить допоміжні функції для використання з новим оператором „with
“. Перегляньте розділ Модуль contextlib, щоб дізнатися більше про цей модуль.Новий модуль: Модуль
cProfile
— це реалізація існуючого модуляprofile
на C, яка має значно менші витрати. Інтерфейс модуля такий самий, як іprofile
: ви запускаєтеcProfile.run('main()')
для профілювання функції, можете зберегти дані профілю у файл тощо. Поки що невідомо, чи профайлер Hotshot, який також написаний мовою C, але не відповідає інтерфейсу модуляprofile
, буде продовжувати підтримуватися в майбутніх версіях Python. (Надав Армін Ріго.)Крім того, модуль
pstats
для аналізу даних, виміряних профайлером, тепер підтримує спрямування виводу до будь-якого файлового об’єкта, надаючи аргумент stream конструкторуStats
. (Надав Скіп Монтанаро.)The
csv
module, which parses files in comma-separated value format, received several enhancements and a number of bugfixes. You can now set the maximum size in bytes of a field by calling thecsv.field_size_limit(new_limit)
function; omitting the new_limit argument will return the currently-set limit. Thereader
class now has aline_num
attribute that counts the number of physical lines read from the source; records can span multiple physical lines, soline_num
is not the same as the number of records read.Синтаксичний аналізатор CSV тепер суворіший щодо багаторядкових полів у лапках. Раніше, якщо рядок закінчувався в полі в лапках без кінцевого символу нового рядка, новий рядок вставлявся у поле, що поверталося. Така поведінка викликала проблеми під час читання файлів, які містили символи повернення каретки в межах полів, тому код було змінено, щоб повертати поле без вставки нового рядка. Як наслідок, якщо нові рядки, вбудовані в поля, є важливими, вхідні дані слід розділити на рядки таким чином, щоб зберегти символи нового рядка.
(Надано Скіпом Монтанаро та Ендрю Макнамарою.)
Клас
datetime
в модуліdatetime
тепер має методstrptime(string, format)
для аналізу рядків дат, наданий Джошем Споеррі. Він використовує символи того самого формату, що йtime.strptime()
іtime.strftime()
:from datetime import datetime ts = datetime.strptime('10:13:15 2006-03-07', '%H:%M:%S %Y-%m-%d')
Метод
SequenceMatcher.get_matching_blocks()
у модуліdifflib
тепер гарантує повернення мінімального списку блоків, що описують відповідні підпослідовності. Раніше алгоритм час від часу розбивав блок відповідних елементів на два записи списку. (Покращення Тім Пітерс.)Модуль
doctest
отримав параметрSKIP
, який утримує приклад від виконання взагалі. Це призначено для фрагментів коду, які є прикладами використання, призначеними для читача, а насправді не є тестовими випадками.Параметр encoding додано до функції
testfile()
і класуDocFileSuite
для визначення кодування файлу. Це полегшує використання символів, відмінних від ASCII, у тестах, що містяться в рядку документації. (Надав Бьорн Тілленіус.)Пакет
email
оновлено до версії 4.0. (Надав Баррі Варшау.)Модуль
fileinput
став більш гнучким. Тепер підтримуються імена файлів у кодуванні Unicode, а параметр mode, який за замовчуванням має значення"r"
, було додано до функціїinput()
, щоб дозволити відкривати файли в двійковому режимі або режимі universal newlines. Ще один новий параметр, openhook, дозволяє використовувати функцію, відмінну відopen()
, щоб відкривати вхідні файли. Коли ви переглядаєте набір файлів, новийfileno()
об’єктаFileInput
повертає дескриптор файлу для поточного відкритого файлу. (Надав Георг Брандл.)У модулі
gc
нова функціяget_count()
повертає 3-кортеж, що містить поточну кількість колекцій для трьох поколінь GC. Це облікова інформація для збирача сміття; коли ці підрахунки досягнуть заданого порогу, буде виконано підмітання сміття. Існуюча функціяgc.collect()
тепер приймає необов’язковий аргумент generation 0, 1 або 2, щоб вказати, яке покоління збирати. (Надав Баррі Варшау.)Функції
nsmallest()
іnlargest()
у модуліheapq
тепер підтримують параметр ключового словаkey
, подібний до того, який надає функціїmin()
/max()
і методиsort()
. Наприклад:>>> import heapq >>> L = ["short", 'medium', 'longest', 'longer still'] >>> heapq.nsmallest(2, L) # Return two lowest elements, lexicographically ['longer still', 'longest'] >>> heapq.nsmallest(2, L, key=len) # Return two shortest elements ['short', 'medium']
(Надав Реймонд Геттінгер.)
Функція
itertools.islice()
тепер приймаєNone
для аргументів start і step. Це робить його більш сумісним з атрибутами об’єктів фрагмента, тож тепер ви можете написати наступне:s = slice(5) # Create slice object itertools.islice(iterable, s.start, s.stop, s.step)
(Надав Реймонд Геттінгер.)
Функцію
format()
в модуліlocale
було змінено та додано дві нові функції,format_string()
іcurrency()
.Параметр val функції
format()
раніше міг бути рядком, якщо з’являлося не більше одного специфікатора %char; тепер параметр має бути точно одним специфікатором %char без навколишнього тексту. Також було додано необов’язковий параметр monetary, який, якщоTrue
, використовуватиме правила локалі для форматування валюти під час розміщення розділювача між групами з трьох цифр.Щоб відформатувати рядки з кількома специфікаторами %char, використовуйте нову функцію
format_string()
, яка працює якformat()
, але також підтримує змішування специфікаторів %char з довільним текстом.Також додано нову функцію
currency()
, яка форматує число відповідно до поточних налаштувань мови.(Надав Георг Брандл.)
Модуль
mailbox
зазнав масштабного перепису, щоб додати можливість змінювати поштові скриньки на додаток до їх читання. Новий набір класів, який включаєmbox
,MH
іMaildir
, використовуються для читання поштових скриньок і мають методadd(message)
для додавання повідомлень,remove(key)
, щоб видалити повідомлення, іlock()
/unlock()
, щоб заблокувати/розблокувати поштову скриньку. Наступний приклад перетворює поштову скриньку у форматі maildir на скриньку у форматі mbox:import mailbox # 'factory=None' uses email.Message.Message as the class representing # individual messages. src = mailbox.Maildir('maildir', factory=None) dest = mailbox.mbox('/tmp/mbox') for msg in src: dest.add(msg)
(Надано Грегорі К. Джонсоном. Фінансування надано Google Summer of Code 2005 року.)
Новий модуль: модуль
msilib
дозволяє створювати файли Microsoft Installer.msi
і файли CAB. Також включено певну підтримку для читання бази даних.msi
. (Надав Мартін фон Льовіс.)Модуль
nis
тепер підтримує доступ до доменів, відмінних від системного домену за замовчуванням, надаючи аргумент domain функціямnis.match()
іnis.maps()
. (Надав Бен Белл.)Функції
itemgetter()
іattrgetter()
модуляoperator
тепер підтримують кілька полів. Такий виклик, якoperator.attrgetter('a', 'b')
поверне функцію, яка отримує атрибутиa
іb
. Поєднання цієї нової функції з параметромkey
методуsort()
дозволяє легко сортувати списки за допомогою кількох полів. (Надав Реймонд Геттінгер.)Модуль
optparse
оновлено до версії 1.5.1 бібліотеки Optik. КласOptionParser
отримав атрибутepilog
, рядок, який друкуватиметься після повідомлення довідки, і методdestroy()
для розриву посилальних циклів, створених об’єктом. (Надав Грег Ворд.)Модуль
os
зазнав кількох змін. Зміннаstat_float_times
тепер має значення true, що означає, щоos.stat()
тепер повертатиме значення часу як числа з плаваючою точкою. (Це не обов’язково означає, щоos.stat()
повертатиме час із точністю до часток секунди; не всі системи підтримують таку точність.)Додано константи з назвами
os.SEEK_SET
,os.SEEK_CUR
іos.SEEK_END
; це параметри функціїos.lseek()
. Дві нові константи для блокування:os.O_SHLOCK
іos.O_EXLOCK
.Було додано дві нові функції
wait3()
іwait4()
. Вони схожі на функціюwaitpid()
, яка очікує на вихід дочірнього процесу та повертає кортеж ідентифікатора процесу та його статус виходу, алеwait3()
іwait4()
повертають додаткову інформацію .wait3()
не приймає ідентифікатор процесу як вхідні дані, тому він очікує на вихід будь-якого дочірнього процесу та повертає 3-кортеж process-id, exit-status, resource-usage як повертається з функціїresource.getrusage()
.wait4(pid)
приймає ідентифікатор процесу. (Надав Чад Дж. Шредер.)У FreeBSD функція
os.stat()
тепер повертає час із наносекундною роздільною здатністю, а повернутий об’єкт тепер маєst_gen
іst_birthtime
. Атрибутst_flags
також доступний, якщо платформа його підтримує. (Надано Антті Луко та Дієго Петтено.)Налагоджувач Python, наданий модулем
pdb
, тепер може зберігати списки команд, які потрібно виконати, коли досягнуто точки зупинки та припинено виконання. Після створення точки зупину №1 введітькоманди 1
та введіть ряд команд, які потрібно виконати, завершивши списоккінець
. Список команд може включати команди, які відновлюють виконання, такі якпродовжити
абодалі
. (Надано Грегуаром Думсом.)Модулі
pickle
іcPickle
більше не приймають повернення значенняNone
від методу__reduce__()
; замість цього метод повинен повертати кортеж аргументів. Можливість повертатиNone
була застарілою в Python 2.4, тож це завершує видалення цієї функції.Модуль
pkgutil
, який містить різноманітні службові функції для пошуку пакунків, було покращено для підтримки перехоплювачів імпорту PEP 302 і тепер також працює для пакунків, що зберігаються в архівах ZIP-формату. (Надав Філіп Дж. Ебі.)Набір тестів pybench від Марка-Андре Лембурга тепер включено до каталогу
Tools/pybench
. Набір pybench є вдосконаленням загальновживаної програмиpystone.py
, оскільки pybench забезпечує більш детальне вимірювання швидкості інтерпретатора. Замість того, щоб виконувати багато різних операцій і зводити результат до одного числа, як це робитьpystone.py
, він відраховує певні операції, такі як виклики функцій, нарізка кортежів, пошук методів і числові операції.Модуль
pyexpat
тепер використовує версію 2.0 аналізатора Expat. (Надав Трент Мік.)Клас
Queue
, наданий модулемQueue
, отримав два нові методи.join()
блокує, доки всі елементи в черзі не будуть отримані та вся робота з обробки елементів не буде завершена. Робочі потоки викликають інший новий метод,task_done()
, щоб повідомити, що обробку елемента завершено. (Надав Реймонд Геттінгер.)Старі модулі
regex
іregsub
, які були застарілими ще з Python 2.0, нарешті були видалені. Інші видалені модулі:statcache
,tzparse
,whrandom
.Також видалено: каталог
lib-old
, який містить старі модулі, такі якdircmp
іni
, було видалено.lib-old
не було вsys.path
за замовчуванням, тому, якщо ваші програми явно не додали каталог доsys.path
, це видалення не повинно вплинути на ваш код.Модуль
rlcompleter
більше не залежить від імпорту модуляreadline
і тому тепер працює на платформах, відмінних від Unix. (Патч від Роберта Кіндла.)Класи
SimpleXMLRPCServer
іDocXMLRPCServer
тепер мають атрибутrpc_paths
, який обмежує операції XML-RPC обмеженим набором URL-шляхів; за замовчуванням дозволено лише'/'
і''/RPC2'
. Встановлення дляrpc_paths
значенняNone
або пустого кортежу вимикає цю перевірку шляху.Модуль
socket
тепер підтримуєAF_NETLINK
сокети в Linux завдяки патчу від Філіпа Біонді. Сокети Netlink — це специфічний для Linux механізм зв’язку між процесом простору користувача та кодом ядра; вступну статтю про них можна знайти на https://www.linuxjournal.com/article/7356. У коді Python адреси мережевих посилань представлені у вигляді кортежу з 2 цілих чисел,(pid, group_mask)
.Два нові методи для об’єктів сокетів,
recv_into(buffer)
іrecvfrom_into(buffer)
, зберігають отримані дані в об’єкті, який підтримує протокол буфера, замість того, щоб повертати дані як рядок. Це означає, що ви можете помістити дані безпосередньо в масив або файл із відображенням пам’яті.Об’єкти сокетів також отримали методи доступу
getfamily()
,gettype()
іgetproto()
для отримання значень сімейства, типу та протоколу для сокета.Новий модуль: модуль
spwd
надає функції для доступу до бази даних тіньових паролів у системах, які підтримують тіньові паролі.struct
тепер працює швидше, оскільки він компілює рядки формату в об’єктиStruct
за допомогою методівpack()
іunpack()
. Це подібно до того, як модульre
дозволяє створювати скомпільовані об’єкти регулярного виразу. Ви все ще можете використовувати функціїpack()
іunpack()
на рівні модуля; вони створять об’єктиStruct
і кешуватимуть їх. Або ви можете безпосередньо використовувати екземпляриStruct
:s = struct.Struct('ih3s') data = s.pack(1972, 187, 'abc') year, number, name = s.unpack(data)
Ви також можете пакувати та розпаковувати дані в буферні об’єкти та з них безпосередньо за допомогою методів
pack_into(buffer, offset, v1, v2, ...)
іunpack_from(buffer, offset)
. Це дає змогу зберігати дані безпосередньо в масиві або файлі, відображеному в пам’яті.(
Struct
об’єкти реалізував Боб Іпполіто під час спринту NeedForSpeed. Підтримку об’єктів буфера додав Мартін Блейс, також під час спринту NeedForSpeed.)Розробники Python перейшли від CVS до Subversion під час процесу розробки 2.5. Інформація про точну версію збірки доступна як змінна
sys.subversion
, 3-кортеж(ім'я-інтерпретатора, ім'я-гілки, діапазон-версій)
. Наприклад, на момент написання моя копія 2.5 повідомляла про('CPython', 'trunk', '45313:45315')
.Ця інформація також доступна для розширень C через функцію
Py_GetBuildInfo()
, яка повертає рядок інформації про збірку, як це:"trunk:45355:45356M, Apr 13 2006, 07:42:19"
. (Надав Баррі Варшау.)Інша нова функція,
sys._current_frames()
, повертає поточні фрейми стека для всіх запущених потоків як словник, що зіставляє ідентифікатори потоку з найвищим фреймом стека, який зараз активний у цьому потоці на момент виклику функції. (Надав Тім Пітерс.)Клас
TarFile
в модуліtarfile
тепер має методextractall()
, який витягує всі члени з архіву в поточний робочий каталог. Також можна встановити інший каталог як ціль видобування та розпакувати лише частину членів архіву.Стиснення, яке використовується для tar-файлу, відкритого в режимі потоку, тепер можна автоматично визначити за допомогою режиму
'r|*'
. (Надав Ларс Густебель.)Модуль
threading
тепер дозволяє встановлювати розмір стеку, який використовується під час створення нових потоків. Функціяstack_size([*size*])
повертає поточний налаштований розмір стека, а надання додаткового параметра size встановлює нове значення. Не всі платформи підтримують зміну розміру стека, але Windows, потоки POSIX і OS/2 підтримують. (Надав Ендрю Макінтайр.)Модуль
unicodedata
оновлено для використання версії 4.1.0 бази даних символів Unicode. Деякі специфікації вимагають версії 3.2.0, тому вона все ще доступна якunicodedata.ucd_3_2_0
.Новий модуль: модуль
uuid
генерує універсальні унікальні ідентифікатори (UUID) відповідно до RFC 4122. RFC визначає кілька різних версій UUID, які генеруються з початкового рядка, властивостей системи або абсолютно випадковим чином. Цей модуль містить класUUID
і функції з іменамиuuid1()
,uuid3()
,uuid4()
іuuid5()
для створення різних версій UUID. (UUID версії 2 не вказано в RFC 4122 і не підтримується цим модулем.)>>> import uuid >>> # make a UUID based on the host ID and current time >>> uuid.uuid1() UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') >>> # make a UUID using an MD5 hash of a namespace UUID and a name >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') >>> # make a random UUID >>> uuid.uuid4() UUID('16fd2706-8baf-433b-82eb-8c7fada847da') >>> # make a UUID using a SHA-1 hash of a namespace UUID and a name >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
(Надано Ка-Пінг Йі.)
Типи
WeakKeyDictionary
іWeakValueDictionary
модуляweakref
отримали нові методи для повторення слабких посилань, що містяться в словнику. Методиiterkeyrefs()
іkeyrefs()
додано доWeakKeyDictionary
, аitervaluerefs()
іvaluerefs()
додано доWeakValueDictionary
. (Надав Фред Л. Дрейк-молодший)Модуль
webbrowser
отримав низку вдосконалень. Тепер його можна використовувати як сценарій зpython -m webbrowser
, приймаючи URL як аргумент; є кілька перемикачів для керування поведінкою (-n
для нового вікна браузера,-t
для нової вкладки). Для підтримки цього додано нові функції на рівні модуля,open_new()
іopen_new_tab()
. Функція модуляopen()
підтримує додаткову функцію, параметр autoraise, який сигналізує, чи піднімати відкрите вікно, коли це можливо. До списку підтримуваних було додано низку додаткових браузерів, таких як Firefox, Opera, Konqueror та elinks. (Надано Олегом Бройтманном і Георгом Брандлом.)Модуль
xmlrpclib
тепер підтримує повернення об’єктівdatetime
для типу дати XML-RPC. Щоб увімкнути цю функцію, укажітьuse_datetime=True
функціїloads()
або класуUnmarshaller
. (Надав Скіп Монтанаро.)Модуль
zipfile
тепер підтримує версію формату ZIP64, тобто архів .zip тепер може бути більшим за 4 ГіБ і містити окремі файли розміром понад 4 ГіБ. (Надав Рональд Уссорен.)Об’єкти
Compress
іDecompress
модуляzlib
тепер підтримують методcopy()
, який створює копію внутрішнього стану об’єкта та повертає новийCompress
абоDecompress
об’єкт. (Надав Кріс Етлі.)
Пакет ctypes¶
Пакет ctypes
, написаний Томасом Геллером, додано до стандартної бібліотеки. ctypes
дозволяє викликати довільні функції в спільних бібліотеках або DLL. Давні користувачі можуть пам’ятати модуль dl
, який надає функції для завантаження спільних бібліотек і виклику функцій у них. Пакет ctypes
набагато привабливіший.
Щоб завантажити спільну бібліотеку або DLL, ви повинні створити екземпляр класу CDLL
і вказати назву або шлях до спільної бібліотеки або DLL. Коли це буде зроблено, ви можете викликати довільні функції, звертаючись до них як до атрибутів об’єкта CDLL
.
import ctypes
libc = ctypes.CDLL('libc.so.6')
result = libc.printf("Line of output\n")
Type constructors for the various C types are provided: c_int()
,
c_float()
, c_double()
, c_char_p()
(equivalent to char
*
), and so forth. Unlike Python’s types, the C versions are all mutable; you
can assign to their value
attribute to change the wrapped value. Python
integers and strings will be automatically converted to the corresponding C
types, but for other types you must call the correct type constructor. (And I
mean must; getting it wrong will often result in the interpreter crashing
with a segmentation fault.)
Ви не повинні використовувати c_char_p()
із рядком Python, коли функція C буде змінювати область пам’яті, тому що рядки Python мають бути незмінними; порушення цього правила призведе до загадкових помилок. Якщо вам потрібна область пам’яті, яку можна змінювати, використовуйте create_string_buffer()
:
s = "this is a string"
buf = ctypes.create_string_buffer(s)
libc.strfry(buf)
Передбачається, що функції C повертають цілі числа, але ви можете встановити атрибут restype
об’єкта функції, щоб змінити це:
>>> libc.atof('2.71828')
-1783957616
>>> libc.atof.restype = ctypes.c_double
>>> libc.atof('2.71828')
2.71828
ctypes
also provides a wrapper for Python’s C API as the
ctypes.pythonapi
object. This object does not release the global
interpreter lock before calling a function, because the lock must be held when
calling into the interpreter’s code. There’s a py_object()
type
constructor that will create a PyObject *
pointer. A simple usage:
import ctypes
d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
ctypes.py_object("abc"), ctypes.py_object(1))
# d is now {'abc', 1}.
Не забудьте використати py_object()
; якщо його пропустити, ви отримаєте помилку сегментації.
ctypes
існує вже деякий час, але люди все ще пишуть і розповсюджують модулі розширення, створені вручну, тому що ви не можете покладатися на наявність ctypes
. Можливо, розробники почнуть писати оболонки Python поверх бібліотеки, доступ до якої здійснюється через ctypes
замість модулів розширення, тепер, коли ctypes
включено до ядра Python.
Дивись також
- http://starship.python.net/crew/theller/ctypes/
The ctypes web page, with a tutorial, reference, and FAQ.
Документація для модуля ctypes
.
Пакет ElementTree¶
Підмножину бібліотеки ElementTree Фредріка Лунда для обробки XML було додано до стандартної бібліотеки як xml.etree
. Доступні модулі ElementTree
, ElementPath
і ElementInclude
з ElementTree 1.2.6. Також включено модуль прискорення cElementTree
.
Решта цього розділу надасть короткий огляд використання ElementTree. Повна документація для ElementTree доступна за адресою https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm.
ElementTree представляє XML-документ як дерево вузлів елементів. Текстовий вміст документа зберігається як атрибути text
і tail
(Це одна з головних відмінностей між ElementTree та об’єктною моделлю документа; у DOM є багато різних типів вузол, включаючи TextNode
.)
Найпоширенішою функцією синтаксичного аналізу є parse()
, яка приймає або рядок (передбачається, що містить ім’я файлу), або файлоподібний об’єкт і повертає екземпляр ElementTree
:
from xml.etree import ElementTree as ET
tree = ET.parse('ex-1.xml')
feed = urllib.urlopen(
'http://planet.python.org/rss10.xml')
tree = ET.parse(feed)
Коли у вас є екземпляр ElementTree
, ви можете викликати його метод getroot()
, щоб отримати кореневий вузол Element
.
Існує також функція XML()
, яка приймає рядковий літерал і повертає вузол Element
(а не ElementTree
). Ця функція забезпечує зручний спосіб об’єднання фрагментів XML, наближаючись до зручності літералу XML:
svg = ET.XML("""<svg width="10px" version="1.0">
</svg>""")
svg.set('height', '320px')
svg.append(elem1)
Кожен елемент XML підтримує деякі методи доступу, подібні до словника, і деякі, подібні до списку. Операції, подібні до словника, використовуються для доступу до значень атрибутів, а операції, подібні до списку, використовуються для доступу до дочірніх вузлів.
Операція |
Результат |
---|---|
|
Повертає n-й дочірній елемент. |
|
Повертає список від m до n дочірніх елементів. |
|
Повертає кількість дочірніх елементів. |
|
Повертає список дочірніх елементів. |
|
Додає elem2 як дитину. |
|
Вставляє elem2 у вказане місце. |
|
Видаляє n-й дочірній елемент. |
|
Повертає список імен атрибутів. |
|
Повертає значення атрибута name. |
|
Встановлює нове значення для атрибута name. |
|
Отримує словник, що містить атрибути. |
|
Видаляє атрибут name. |
Коментарі та інструкції з обробки також представлені у вигляді вузлів Element
. Щоб перевірити, чи є вузол коментарем або інструкцією з обробки:
if elem.tag is ET.Comment:
...
elif elem.tag is ET.ProcessingInstruction:
...
Щоб згенерувати вивід XML, вам слід викликати метод ElementTree.write()
. Як і parse()
, він може приймати або рядок, або файлоподібний об’єкт:
# Encoding is US-ASCII
tree.write('output.xml')
# Encoding is UTF-8
f = open('output.xml', 'w')
tree.write(f, encoding='utf-8')
(Увага: кодування за замовчуванням, яке використовується для виводу, — ASCII. Для загальної роботи з XML, де ім’я елемента може містити довільні символи Unicode, ASCII не є дуже корисним кодуванням, оскільки воно спричинить виключення, якщо ім’я елемента містить будь-які символи зі значеннями більше 127. Тому найкраще вказати інше кодування, наприклад UTF-8, яке може обробляти будь-який символ Unicode.)
Цей розділ є лише частковим описом інтерфейсів ElementTree. Щоб дізнатися більше, прочитайте офіційну документацію пакета.
Дивись також
- https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm
Офіційна документація для ElementTree.
Пакет hashlib¶
На заміну модулів md5
і sha
додано новий модуль hashlib
, написаний Грегорі П. Смітом. hashlib
додає підтримку додаткових безпечних хешів (SHA-224, SHA-256, SHA-384 і SHA-512). Якщо доступний, модуль використовує OpenSSL для швидкої оптимізованої реалізації алгоритмів.
Старі модулі md5
і sha
все ще існують як оболонки навколо хешлібу для збереження зворотної сумісності. Інтерфейс нового модуля дуже близький до інтерфейсу старих модулів, але не ідентичний. Найсуттєвіша відмінність полягає в тому, що функції конструктора для створення нових об’єктів хешування називаються по-різному.
# Old versions
h = md5.md5()
h = md5.new()
# New version
h = hashlib.md5()
# Old versions
h = sha.sha()
h = sha.new()
# New version
h = hashlib.sha1()
# Hash that weren't previously available
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()
# Alternative form
h = hashlib.new('md5') # Provide algorithm as a string
Після створення хеш-об’єкта його методи залишаються такими ж, як і раніше: update(string)
хешує вказаний рядок у поточний стан дайджесту, digest()
і hexdigest()
повертають дайджест значення у вигляді двійкового рядка або рядка шістнадцяткових цифр, а copy()
повертає новий об’єкт хешування з тим самим станом дайджесту.
Дивись також
Документація для модуля hashlib
.
Пакет sqlite3¶
The pysqlite module (http://www.pysqlite.org), a wrapper for the SQLite embedded
database, has been added to the standard library under the package name
sqlite3
.
SQLite — це бібліотека C, яка надає легку дискову базу даних, яка не потребує окремого серверного процесу та дозволяє отримувати доступ до бази даних за допомогою нестандартного варіанту мови запитів SQL. Деякі програми можуть використовувати SQLite для внутрішнього зберігання даних. Також можна створити прототип програми за допомогою SQLite, а потім перенести код у більшу базу даних, таку як PostgreSQL або Oracle.
pysqlite був написаний Герхардом Херінгом і забезпечує інтерфейс SQL, сумісний зі специфікацією DB-API 2.0, описаною PEP 249.
Якщо ви компілюєте вихідні коди Python самостійно, зауважте, що дерево вихідних кодів не містить код SQLite, а містить лише модуль оболонки. Вам потрібно буде встановити бібліотеки та заголовки SQLite перед компіляцією Python, і процес збирання скомпілює модуль, коли необхідні заголовки будуть доступні.
Щоб використовувати модуль, ви повинні спочатку створити об’єкт Connection
, який представлятиме базу даних. Тут дані зберігатимуться у файлі /tmp/example
:
conn = sqlite3.connect('/tmp/example')
Ви також можете вказати спеціальну назву :memory:
, щоб створити базу даних в RAM.
Коли у вас є Connection
, ви можете створити об’єкт Cursor
і викликати його метод execute()
для виконання команд SQL:
c = conn.cursor()
# Create table
c.execute('''create table stocks
(date text, trans text, symbol text,
qty real, price real)''')
# Insert a row of data
c.execute("""insert into stocks
values ('2006-01-05','BUY','RHAT',100,35.14)""")
Зазвичай ваші операції SQL повинні використовувати значення зі змінних Python. Ви не повинні складати свій запит за допомогою рядкових операцій Python, оскільки це небезпечно; це робить вашу програму вразливою до SQL-атаки.
Замість цього використовуйте підстановку параметрів DB-API. Помістіть ?
як покажчик місця заповнення, де ви хочете використовувати значення, а потім надайте кортеж значень як другий аргумент для методу execute()
курсора. (Інші модулі бази даних можуть використовувати інший заповнювач, наприклад %s
або :1
.) Наприклад:
# Never do this -- insecure!
symbol = 'IBM'
c.execute("... where symbol = '%s'" % symbol)
# Do this instead
t = (symbol,)
c.execute('select * from stocks where symbol=?', t)
# Larger example
for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
('2006-04-06', 'SELL', 'IBM', 500, 53.00),
):
c.execute('insert into stocks values (?,?,?,?,?)', t)
Щоб отримати дані після виконання оператора SELECT, ви можете розглядати курсор як ітератор, викликати метод курсора fetchone()
, щоб отримати один відповідний рядок, або викликати fetchall()
, щоб отримати список відповідні рядки.
У цьому прикладі використовується форма ітератора:
>>> c = conn.cursor()
>>> c.execute('select * from stocks order by price')
>>> for row in c:
... print row
...
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)
(u'2006-04-06', u'SELL', u'IBM', 500, 53.0)
(u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
>>>
Для отримання додаткової інформації про діалект SQL, який підтримує SQLite, див. https://www.sqlite.org.
Дивись також
- http://www.pysqlite.org
Веб-сторінка pysqlite.
- https://www.sqlite.org
Веб-сторінка SQLite; документація описує синтаксис і доступні типи даних для підтримуваного діалекту SQL.
Документація для модуля sqlite3
.
- PEP 249 - Специфікація API бази даних 2.0
PEP, написаний Марком-Андре Лембургом.
Пакет wsgiref¶
Інтерфейс шлюзу веб-сервера (WSGI) v1.0 визначає стандартний інтерфейс між веб-серверами та веб-додатками Python і описаний у PEP 333. Пакет wsgiref
є еталонною реалізацією специфікації WSGI.
Пакет містить базовий HTTP-сервер, який запускатиме програму WSGI; цей сервер корисний для налагодження, але не призначений для використання у виробництві. Налаштування сервера займає лише кілька рядків коду:
from wsgiref import simple_server
wsgi_app = ...
host = ''
port = 8000
httpd = simple_server.make_server(host, port, wsgi_app)
httpd.serve_forever()
Дивись також
- http://www.wsgi.org
Центральний веб-сайт для ресурсів, пов’язаних з WSGI.
- PEP 333 - Інтерфейс шлюзу веб-сервера Python v1.0
PEP, написаний Філіпом Дж. Ебі.
Зміни збірки та C API¶
Зміни в процесі збирання Python і в API C включають:
Дерево вихідних кодів Python було перетворено з CVS на Subversion у складній процедурі міграції, яка контролювалася та бездоганно виконана Мартіном фон Льовісом. Процедура була розроблена як PEP 347.
Coverity, компанія, яка продає інструмент аналізу вихідного коду під назвою Prevent, надала результати свого дослідження вихідного коду Python. Аналіз виявив близько 60 помилок, які були швидко виправлені. Багато помилок були проблемами повторного підрахунку, які часто траплялися в коді обробки помилок. Перегляньте статистику https://scan.coverity.com.
The largest change to the C API came from PEP 353, which modifies the interpreter to use a
Py_ssize_t
type definition instead ofint
. See the earlier section PEP 353: використання ssize_t як типу індексу for a discussion of this change.Дизайн компілятора байт-коду значно змінився, більше не генеруючи байт-код шляхом обходу дерева аналізу. Замість цього дерево синтаксичного аналізу перетворюється на абстрактне синтаксичне дерево (або AST), і це абстрактне синтаксичне дерево обходиться для отримання байт-коду.
Код Python може отримати об’єкти AST, використовуючи вбудований
compile()
і вказавши_ast.PyCF_ONLY_AST
як значення параметра flags:from _ast import PyCF_ONLY_AST ast = compile("""a=0 for i in range(10): a += i """, "<string>", 'exec', PyCF_ONLY_AST) assignment = ast.body[0] for_loop = ast.body[1]
Офіційна документація для коду AST ще не написана, але PEP 339 обговорює дизайн. Щоб почати вивчати код, прочитайте визначення різних вузлів AST у
Parser/Python.asdl
. Сценарій Python читає цей файл і генерує набір визначень структури C уInclude/Python-ast.h
.PyParser_ASTFromString()
іPyParser_ASTFromFile()
, визначені уInclude/pythonrun.h
, приймають джерело Python як вхідні дані та повертають корінь AST, що представляє вміст. Потім цей AST можна перетворити на об’єкт коду за допомогоюPyAST_Compile()
. Щоб дізнатися більше, прочитайте вихідний код, а потім поставте запитання на python-dev.Код AST був розроблений під керівництвом Джеремі Гілтона та впроваджений (в алфавітному порядку) Бреттом Кенноном, Ніком Когланом, Грантом Едвардсом, Джоном Ересманом, Куртом Кайзером, Нілом Норвітцем, Тімом Пітерсом, Арміном Ріго та Нілом Шеменауером, а також учасниками ряд спринтів AST на конференціях, таких як PyCon.
Було застосовано патч Евана Джонса для obmalloc, вперше описаний у виступі на PyCon DC 2005. Python 2.4 розподіляв невеликі об’єкти на аренах розміром 256 КБ, але ніколи не звільняв арен. За допомогою цього патча Python звільнить арени, коли вони порожні. Чистий ефект полягає в тому, що на деяких платформах, коли ви виділяєте багато об’єктів, використання пам’яті Python може фактично зменшитися, коли ви їх видаляєте, і пам’ять може повертатися до операційної системи. (Реалізовано Еваном Джонсом і перероблено Тімом Пітерсом.)
Зауважте, що ця зміна означає, що модулі розширення повинні бути більш обережними під час розподілу пам’яті. API Python має багато різних функцій для розподілу пам’яті, згрупованих у родини. Наприклад,
PyMem_Malloc()
,PyMem_Realloc()
іPyMem_Free()
є однією сім’єю, яка виділяє необроблену пам’ять, тоді якPyObject_Malloc()
, :cPyObject_Realloc()
іPyObject_Free()
— ще одне сімейство, яке має використовуватися для створення об’єктів Python.Раніше всі ці різні родини зводилися до функцій платформи
malloc()
іfree()
. Це означало, що не мало значення, якщо ви зробили щось не так і виділили пам’ять за допомогою функціїPyMem()
, але звільнили її за допомогою функціїPyObject()
. Зі змінами obmalloc у версії 2.5 ці родини тепер виконують різні речі, і невідповідності, ймовірно, призведуть до помилки сегмента. Ви повинні ретельно протестувати свої модулі розширення C за допомогою Python 2.5.Вбудовані типи наборів тепер мають офіційний C API. Викличте
PySet_New()
іPyFrozenSet_New()
, щоб створити новий набір,PySet_Add()
іPySet_Discard()
, щоб додати та видалити елементи, і :cPySet_Contains()
іPySet_Size()
для перевірки стану набору. (Надав Реймонд Геттінгер.)Код C тепер може отримати інформацію про точну версію інтерпретатора Python, викликавши функцію
Py_GetBuildInfo()
, яка повертає рядок інформації про збірку, як це:"trunk:45355:45356M, 13 квітня 2006 р., 07 :42:19"
. (Надав Баррі Варшау.)Два нові макроси можна використовувати для позначення функцій C, які є локальними для поточного файлу, щоб можна було використовувати швидший виклик.
Py_LOCAL(type)
оголошує функцію як таку, що повертає значення вказаного типу, і використовує кваліфікатор швидкого виклику.Py_LOCAL_INLINE(type)
робить те саме, а також запитує вбудовування функції. ЯкщоPY_LOCAL_AGGRESSIVE()
визначено до включенняpython.h
, для модуля вмикається набір більш агресивних оптимізацій; ви повинні порівняти результати, щоб дізнатися, чи справді ці оптимізації роблять код швидшим. (Надано Фредріком Лундом під час спринту NeedForSpeed.)PyErr_NewException(name, base, dict)
тепер може приймати кортеж базових класів як свій аргумент base. (Надав Георг Брандл.)Функція
PyErr_Warn()
для видачі попереджень тепер застаріла на користьPyErr_WarnEx(category, message, stacklevel)
, яка дозволяє вказати кількість кадрів стека, що відокремлюють цю функцію та виклик. Stacklevel 1 — це функція, яка викликаєPyErr_WarnEx()
, 2 — це функція, яка стоїть вище, і так далі. (Додав Ніл Норвіц.)Інтерпретатор CPython все ще написаний на C, але тепер код можна скомпілювати за допомогою компілятора C++ без помилок. (Реалізовано Ентоні Бакстером, Мартіном фон Льовісом, Скіпом Монтанаро.)
Функцію
PyRange_New()
видалено. Він ніколи не був задокументований, ніколи не використовувався в коді ядра та мав небезпечно слабку перевірку помилок. У малоймовірному випадку, коли ваші розширення використовували його, ви можете замінити його чимось подібним до наступного:range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll", start, stop, step);
Зміни, що стосуються порту¶
MacOS X (10.3 і вище): динамічне завантаження модулів тепер використовує функцію
dlopen()
замість специфічних для MacOS функцій.MacOS X: перемикач
--enable-universalsdk
додано до сценарію configure, який компілює інтерпретатор як універсальний двійковий файл, здатний працювати на процесорах PowerPC і Intel. (Надав Рональд Оуссорен; bpo-2573.)Windows:
.dll
більше не підтримується як розширення імені файлу для модулів розширення..pyd
тепер є єдиним розширенням імені файлу, яке шукатиметься.
Перенесення на Python 2.5¶
У цьому розділі перераховано описані раніше зміни, які можуть потребувати змін у вашому коді:
ASCII тепер є стандартним кодуванням для модулів. Тепер це синтаксична помилка, якщо модуль містить рядкові літерали з 8-бітовими символами, але не має оголошення кодування. У Python 2.4 це викликало попередження, а не синтаксичну помилку.
Раніше атрибут
gi_frame
генератора завжди був об’єктом фрейму. Через зміни PEP 342, описані в розділі PEP 342: Нові функції генератора, теперgi_frame
може мати значенняNone
.Нове попередження,
UnicodeWarning
, спрацьовує, коли ви намагаєтеся порівняти рядок Unicode з 8-бітним рядком, який не можна перетворити на Unicode за допомогою стандартного кодування ASCII. Раніше такі порівняння викликали винятокUnicodeDecodeError
.Бібліотека: модуль
csv
тепер суворіше щодо багаторядкових полів у лапках. Якщо ваші файли містять символи нового рядка, вбудовані в поля, вхідні дані слід розділити на рядки таким чином, щоб символи нового рядка зберігалися.Бібліотека: функція
format()
модуляlocale
раніше приймала будь-який рядок, якщо з’являлося не більше одного специфікатора %char. У Python 2.5 аргумент має бути точно одним специфікатором %char без навколишнього тексту.Бібліотека: модулі
pickle
іcPickle
більше не приймають значення, що повертаєтьсяNone
від методу__reduce__()
; замість цього метод повинен повертати кортеж аргументів. Модулі також більше не приймають застарілий параметр ключового слова bin.Бібліотека: класи
SimpleXMLRPCServer
іDocXMLRPCServer
тепер мають атрибутrpc_paths
, який обмежує операції XML-RPC обмеженим набором URL-шляхів; за замовчуванням дозволено лише'/'
і''/RPC2'
. Встановлення дляrpc_paths
значенняNone
або пустого кортежу вимикає цю перевірку шляху.C API: Many functions now use
Py_ssize_t
instead ofint
to allow processing more data on 64-bit machines. Extension code may need to make the same change to avoid warnings and to support 64-bit machines. See the earlier section PEP 353: використання ssize_t як типу індексу for a discussion of this change.C API: The obmalloc changes mean that you must be careful to not mix usage of the
PyMem_*()
andPyObject_*()
families of functions. Memory allocated with one family’s*_Malloc()
must be freed with the corresponding family’s*_Free()
function.
Подяки¶
Автор хотів би подякувати наступним особам за пропозиції, виправлення та допомогу з різними чернетками цієї статті: Георг Брандл, Нік Коглан, Філіп Дж. Ебі, Ларс Густебель, Раймонд Геттінгер, Ральф В. Гроссе-Кунстлев, Кент Джонсон, Йен Лоу, Мартін фон Льовіс, Фредрік Лунд, Ендрю Макнамара, Скіп Монтанаро, Густаво Німейєр, Пол Прескод, Джеймс Прайор, Майк Ровнер, Скотт Вайкарт, Баррі Варсоу, Томас Воутерс.