Этот API был определен для поощрения сходства между модулями Python, используемыми для доступа к базам данных. Таким образом мы надеемся достичь соответствия, которое приведет к более понятным модулям, коду, который в целом легче переносим между базами данных и более широкому спектру возможностей языка Python по доступу к базам данных.
Спецификация интерфейса состоит из нескольких разделов:
Комментарии и вопросы по этой спецификации могут быть направлены в адрес Специальной группы по доступу к базам данных из Python.
За дополнительной информацией о доступе к базам данных из Python и о имеющихся пакетах обращайтесь к Руководству по базам данных на www.python.org.
Этот документ описывает Python Database API Specification 2.0. Предыдущая версия 1.0 все еще доступна для справки. Поощряется использование последней версии спецификации в качестве основы для нового интерфейса программистами, пишущими пакеты.
Доступ к базе данных реализуется с помощью объектов соединения (connection objects). Модуль должен предоставлять для них следующий конструктор:
Должны быть определены следующие глобальные переменные модуля:
'1.0'
и '2.0'
.0
= Модуль не может разделяться нитями.1
= Нити могут разделять модуль, но не соединения.2
= Нити могут разделять и модуль, и соединения.3
= Нити могут разделять модуль, соединения и курсоры.'qmark'
= Стиль вопроса, например '...WHERE name=?''numeric'
= Числовой (позиционный) маркер, например '...WHERE name=:1''named'
= Именованный маркер, например '...WHERE name=:name''format'
= Коды формата ANSI C printf, например '...WHERE name=%s''pyformat'
= Расширенные коды формата языка Python, например '...WHERE name=%(name)s'Модуль должен обеспечивать всю информацию об ошибках с помощью следующих исключений или их подклассов:
Вот схема наследования исключений:
StandardError
|__Warning
|__Error
|__InterfaceError
|__DatabaseError
|__DataError
|__OperationalError
|__IntegrityError
|__InternalError
|__ProgrammingError
|__NotSupportedError
Примечание: Значения этих исключений не определены. Они должны отчетливо подсказывать пользователю, что именно пошло не так.
Объекты соединения должны реагировать на следующие вызовы:
Эти объекты представляют курсор базы данных, используемый для управления контекстом операции выборки.
Объекты курсора должны поддерживать следующие методы и атрибуты:
name, type_code, display_size, internal_size, precision, scale, null_ok
). Этот атрибут будет принимать значение None для операций, не возвращающих строки или в случае, когда курсор еще не выполнил операцию с помощью метода executeXXX()
.Type_code
может интерпретироваться путем сравнения его с Объектами типа, определенными в следующем разделе.select
) или затронутое (для модифицирующих предложений DML наподобие update
или insert
) последним вызовом executeXXX()
.executeXXX()
или если интерфейс не может определить количество строк в последней операции.[7]fetchXXX()
.Error
(или подкласс).paramstyle
). [5]executemany()
.seq_of_parameters
.execute()
, применимы также и к этому методу.None
в случае, когда данных больше нет. [6]Error
(или подкласс) возбуждается, если предыдущий вызов executeXXX()
не вернул результирующего множества, либо еще не было ни одного такого вызова.arraysize
. Этот метод должен попытаться выбрать столько строк, сколько указано в параметре. Если такое количество строк недоступно, может быть возвращено меньшее число строк.Error
(или подкласс) возбуждается, если предыдущий вызов executeXXX()
не вернул результирующего множества, либо еще не было ни одного такого вызова.arraysize
. Если используется параметр размера, то лучше, чтобы он сохранял одну и ту же величину от одного вызова fetchmany()
к следующему.arraysize
может влиять на производительность этой операции.Error
(или подкласс) возбуждается, если предыдущий вызов executeXXX()
не вернул результирующего множества, либо еще не было ни одного такого вызова.None
. Иначе он возвращает значение истинности, и последующие обращения к методам выборки будут возвращать строки из следующего результирующего множества.Error
(или подкласс) возбуждается, если предыдущий вызов executeXXX()
не вернул результирующего множества, либо еще не было ни одного такого вызова.fetchmany()
за один раз. По умолчанию имеет значение 1, означающее выборку одной строки за один раз.fetchmany()
, однако они имеют полное право выбирать по одной строке за раз при взаимодействии с базой данных. Этот атрибут может быть также использован в реализации executemany()
.executeXXX()
для предварительного определения областей памяти под параметры операции.sizes
(размеры) определен как последовательность - один элемент для каждого входного параметра. Элемент должен быть объектом типа (Type Object, например, IntType), соответствующим типу параметра, или целым числом, определяющим максимальную длину строкового параметра. Если элемент имеет значение None
, под этот столбец не будет зарезервировано заранее определенной области памяти (это полеэно, чтобы избежать выделения областей для больших вводов).executeXXX()
.executeXXX()
.Многие базы данных требуют входных данных в определенном формате для привязки к input-параметрам операций. Например, если данные предназначены для столбца типа DATE, они должен быть подготовлены для базы данных в определенном строковом формате. Такие же проблемы существуют для столбцов "Row ID" или больших бинарных элементов (например, blob'ов или столбцов RAW). Это представляет проблему для Python, поскольку параметры метода executeXXX()
не типизированы. Когда модуль базы данных видит строковый объект Python, он не знает, нужно ли его привязывать как простой символьный столбец (CHAR), как необработанный бинарный элемент (BINARY) или как дату (DATE).
Для преодоления этой проблемы модуль должен обеспечивать описанные ниже конструкторы для создания объектов, которые могут хранить специальные значения. Когда такой объект передется методам курсора, модуль может определить правильный тип входного параметра и привязать его соответствующим образом.
Атрибут объекта курсора description
возвращает информацию о каждом из столбцов результата запроса. Код типа type_code
должен быть проверен на равенство одному из Объектов типа, описанных ниже. Объекты типа могут быть равны более чем одному коду типа (например, DATETIME может быть равен кодам типа для столбцов даты, времени и временной метки; подробно см. Советы по реализации, данные ниже).
Модуль экспортирует следующие конструкторы и одноэлементные множества:
NULL-значения SQL представляются с помощью None при вводе и выводе.
Примечание: Использование отсчетов Unix при взаимодействии с базой данных может создать проблемы из-за ограниченности спектра описываемых ими дат.
Include/bufferobject.h
и Objects/bufferobject.c
в исходниках Python.
import time
def DateFromTicks(ticks):
return apply(Date,time.localtime(ticks)[:3])
def TimeFromTicks(ticks):
return apply(Time,time.localtime(ticks)[3:6])
def TimestampFromTicks(ticks):
return apply(Timestamp,time.localtime(ticks)[:6])
class DBAPITypeObject:
def __init__(self,*values):
self.values = values
def __cmp__(self,other):
if other in self.values:
return 0
if other < self.values:
return 1
else:
return -1
import exceptions
class Error(exceptions.StandardError):
pass
class Warning(exceptions.StandardError):
pass
class InterfaceError(Error):
pass
class DatabaseError(Error):
pass
class InternalError(DatabaseError):
pass
class OperationalError(DatabaseError):
pass
class ProgrammingError(DatabaseError):
pass
class IntegrityError(DatabaseError):
pass
class DataError(DatabaseError):
pass
class NotSupportedError(DatabaseError):
pass
Python Database API 2.0 вводит несколько значительных изменений относительно версии 1.0. Ввиду того, что некоторые из этих изменений приведут к нарушению работы существующих скриптов, основанных на DB API 1.0, старший номер версии был увеличен для отражения этого изменения.
Вот наиболее важные изменения между версиями 1.0 и 2.0:
Несмотря на то, что спецификация версии 2.0 прояснила многие из вопросов, оставленных открытыми в версии 1.0, остается еще несколько проблем:
1. В качестве руководящего указания параметры конструктора соединения должны быть реализованы как ключевые параметры для более интуитивного использования и согласно следующей последовательности параметров:
dsn |
= Источник данных в виде строки | |
user |
= Имя пользователя в виде строки | (необязательно) |
password |
= Пароль в виде строки | (необязательно) |
host |
= Имя хоста | (необязательно) |
database |
= Имя базы данных | (необязательно) |
Например, соединение может выглядеть следующим образом:
connect(dsn='myhost:MYDB',user='guido',password='234$')
2. Реализаторы модуля должны отдавать предпочтение 'numeric', 'named' и 'pyformat' перед другими форматами, так как это предполагает большую четкость и гибкость.
3. Если база данных не поддерживает функцию, необходимую для метода, интерфейс должен возбуждать исключение при попытке использования этого метода.
Предпочтительный подход заключается в отказе от реализации такого метода, тем самым приводя к генерации языком Python исключения AttributeError
в случае, если запрашивается этот метод. Это позволяет программисту проверить возможности базы данных, используя стандартную функцию hasattr()
.
Для некоторых динамически конфигурируемых интерфейсов может не годиться необходимость динамического создания метода. Эти интерфейсы в таком случае должны вызывать исключение NotSupportedError
для указания на невозможность исполнения отката, когда метод уже вызван.
4. Интерфейс базы данных может поддержать именованные курсоры путем разрешения строкового аргумента для метода. Это свойство не является частью спецификации, поскольку оно усложняет семантику методов .fetchXXX()
.
5. Модуль будет использовать метод __getitem__ объекта параметров для отображения как позиций (целых чисел), так и имен (строк) в значения параметров. Это позволяет использовать в качестве входных величин как последовательности, так и словари.
Термин "привязка" относится к процессу привязки входного значения к буферу выполнения базы данных. В практических терминах это означает, что входное значение напрямую используется в качестве значения в операции. От клиента не должно требоваться "выделение" ("escaping") этого значения таким образом, чтобы его можно было использовать - значение должно быть равно действительному значению из базы данных.
6. Заметьте, что интерфейс может реализовывать выборку строк с использованием массивов и другие виды оптимизации. Нет гарантии, что обращение к этому методу сдвинет соответствующий курсор вперед только на одну строку.
7. Атрибут rowcount
может быть запрограммирован способом, динамически обновляющим его значение. Это может быть полезно для баз данных, возвращающих осмысленные значения rowcount только после первого вызова метода .fetchXXX()
.