RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
YandexMoney: 
41001198119846 
E-gold:
5128052

5.7 Спецификация Python Database API 2.0

Этот API был определен, чтобы привести к одному знаменателю модули Python, которые используются, чтобы обратиться к базам данных. Этот документ описывает Python Database API 2.0. Спецификация интерфейса состоит из нескольких разделов:

Комментарии и вопросы относительно этой спецификации могут быть направлены на db-sig@python.org.

Для получения большего количества информации относительно связи с помощью интерфейса базы данных с Python и о доступных пакетах изучите руководство на http://www.python.org/topics/database.

5.7.1 Интерфейс модулей

Доступ к базе данных сделан доступным через объекты подключения. Модуль должен обеспечивать конструктор для них:

connect(parameters...)
Конструктор для создания подключения с базой данных. Возвращает объект подключения. Требуется ряд параметров, которые являются зависимыми от базы данных.

Эти глобальные переменные модуля должны быть определены:

apilevel
Строковая константа, устанавливающая поддержанный уровень DB API. В настоящее время допустимы только строки '1.0' и '2.0'. Если не задана, предполагается уровень интерфейса Database API 1.0.
threadsafety
Целочисленная константа, устанавливающая уровень безопасности потоков, который интерфейс поддерживает. Возможные значения:
0 Потоки не могут совместно использовать модуль.
1 Потоки могут совместно использовать модуль, но не подключения.
2 Потоки могут совместно использовать модуль и подключения.
3 Потоки могут совместно использовать модуль, курсоры и подключения.

Совместное использование в вышеупомянутом контексте означает, что два потока могут использовать ресурс без того, чтобы применять mutex-семафор, чтобы выполнить блокировку ресурса. Обратите внимание, что Вы не можете всегда делать внешние ресурсы поточно-безопасными управляя доступом, использующим mutex: ресурс может полагаться на глобальные переменные или другие внешние источники данных, которые находятся вне Вашего управления!

paramstyle
Строковая константа. Устанавливает тип маркера параметра, форматирующего ожидаемый интерфейсом. Возможные значения:
'qmark' Стиль метки запроса, например, '...WHERE name=?'
'numeric' Числовой, позиционный стиль, например, '...WHERE name=:1'
'named' Именованный стиль, например, '...WHERE name=:name'
'format' Формат кодов ANSI C printf, например, '...WHERE name=%s'
'pyformat' Расширенные форматные коды языка Python, например, '...WHERE name=%(name)s'

Модуль должен делать всю информацию об ошибках доступной через эти исключительные ситуации или через подклассы от них:

Warning
Исключительная ситуация для важных предупреждений подобно усечениям данных при вставке и т. д. Это должно быть подклассом от Python StandardError.
Error
Исключительная ситуация, которая является основным классом для всех других исключительных ситуаций ошибки. Вы можете использовать это, чтобы захватить все ошибки с одиночной частью 'except'. Предупреждения не считаются ошибками и таким образом не должны использовать этот класс как ядро. Это обязательно должно быть подклассом Python StandardError.
InterfaceError
Исключительная ситуация для ошибок, которые связаны с интерфейсом базы данных, а не с самой базой данных. Это должно быть подклассом Error.
DatabaseError
Исключительная ситуация для ошибок, которые связаны с самой базой данных. Это должно быть подклассом Error.
DataError
Исключительная ситуация для ошибок, которые появляются из-за проблем с обработанными данными, подобно делению на ноль, числовое значение вне диапазона и т.д. Это должно быть подклассом DatabaseError.
OperationalError
Исключительная ситуация для ошибок, которые связаны с работой с базой данных и не обязательно подконтрольны программисту, например, непредвиденное разъединение, имя источника данных не найдено, транзакция не могла быть обработана, ошибка распределения памяти произошла в течение обработки и т.д. Это должно быть подклассом от DatabaseError.
IntegrityError
Исключительная ситуация вызывается, когда воздействуют на реляционную целостность базы данных, например, произошла ошибка проверки внешних ключей. Это должно быть подклассом от DatabaseError.
InternalError
Исключительная ситуация для случаев, когда база данных сталкивается с внутренней ошибкой, например, курсор больше не имеет силу, транзакция вышла из синхронизации, либо случилось что-то в этом роде. Это должно быть подклассом от DatabaseError.
ProgrammingError
Исключительная ситуация для ошибок программирования, например, таблица не найдена или уже существует, ошибка синтаксиса в инструкции SQL, неправильное число определенных параметров и т.д. Это должно быть подклассом DatabaseError.
NotSupportedError
Исключительная ситуация для ситуации, когда использовался метод или API базы данных, который не поддержан базой данных, например, запрашивается rollback() на подключении, которое не поддерживает транзакции или имеет выключенные транзакции. Это должно быть подклассом DatabaseError.

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

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

Это размещение наследования исключительной ситуации:

StandardError
|__Warning
|__Error
   |__InterfaceError
   |__DatabaseError
      |__DataError
      |__OperationalError
      |__IntegrityError
      |__InternalError
      |__ProgrammingError
      |__NotSupportedError

Обратите внимание: значения этих исключительных ситуаций не определены. Они должны дать пользователю информацию о том, что пошло не так.

5.7.2 Объекты подключения

Объекты подключения должны отвечать на следующие методы:

close()
Закрыть подключение немедленно. Подключение будет непригодным, начиная с этого момента. Если с ним попытаться что-то сделать, будет вызвана исключительная ситуация Error (или подкласс от нее). То же самое применяется ко всем объектам курсора, пробующим использовать подключение.
commit()
Передать любую ждущую обработки транзакцию на базу данных. Обратите внимание, что если база данных поддерживает auto-commit, это свойство надо заранее выключить. Метод интерфейса можно обеспечивать, чтобы иметь возможность отмены изменений.

Модули баз данных, которые не поддерживают транзакции, должны выполнить этот метод с не имеющими силу функциональными возможностями.

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

Параметры конструктора подключения должны быть выполнены как параметры ключевого слова для более интуитивного использования и следовать этому порядку параметров:
dsn Источник данных как строка обязательно
user Имя пользователя как строка опционально
password Пароль пользователя как строка опционально
host Имя хоста опционально
database Имя базы данных опционально

Например, конструктор подключения мог бы выглядеть следующим образом: connect(dsn='myhost:MYDB',user='guido',password='234+$').

5.7.3 Объекты курсоров

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

Объекты курсоров должны отвечать на следующие методы и атрибуты:

description
Этот атрибут только для чтения: последовательность последовательностей с 7 элементами. Каждая из этих последовательностей содержит информацию, описывающую один столбец результата: (name, type_code, display_size, internal_size, precision, scale, null_ok). Этот атрибут будет None для операций, которые не возвращают строки, или если курсор не имел операции, вызываемой через метод executeXXX().

Код type_code может интерпретироваться, сравнивая его с Type Objects, определенными в разделе ниже.

rowcount
Этот атрибут только для чтения определяет число строк, обработанных последним вызовом executeXXX() (для SQL-инструкций, вроде select) или затронутых запросом (для SQL-инструкций, подобных update или insert). Атрибут равен -1 в случае, если никакой executeXXX() не выполнился на курсоре.
callproc(procname[,parameters])
Этот метод факультативный: все базы данных обеспечивают хранимые процедуры. Вызывает хранимую процедуру базы данных с данным именем. Последовательность параметров должна содержать одну запись для каждого параметра, который процедура ожидает. Результат обращения будет возвращен как изменяемая копия входной последовательности. Входные параметры оставлены нетронутыми, выводимые и вводимо-выводимые параметры будут заменены на возможно новые значения. Процедура может также обеспечивать набор результатов как вывод. Это затем должно быть сделано доступным через стандартные методы fetchXXX().
close()
Закрывает курсор немедленно и делает его непригодным, начиная с текущего момента. При попытке что-либо с ним сделать еще, будет вызвана исключительная ситуация Error (или ее подкласс).
execute(operation[,parameters])
Препарирует и выполняет операцию базы данных (запрос или команду). Параметры можно обеспечивать как последовательность или отображение. Переменные определены в специфической для базы данных записи. Значения возврата не определены.

Ссылка на операцию будет сохраняться курсором. Если тот же самый объект операции передан снова, то курсор может оптимизировать поведение. Это наиболее эффективно для алгоритмов, где много раз используется та же самая операция, но с разными параметрами. Для достижения максимальной эффективности при многократном использовании операции, самое лучшее использовать метод setinputsizes(), чтобы определить типы параметра и размеры. Для параметра допустимо не соответствовать предопределенной информации: реализация должна это скомпенсировать, возможно, с потерей эффективности.

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

executemany(operation,seq_of_parameters)
Готовит операцию базы данных (запрос или команду), а затем выполняет это для всех последовательностей параметров или отображений, найденных в последовательности seq_of_parameters.

Модули могут выполнить этот метод, используя многократные обращения к методу execute() или используя операции массива, чтобы база данных обработала всю последовательность в целом в одном обращении.

Те же самые комментарии, что касаются execute(), также применяются к этому методу. Значения возврата не определены.

fetchone()
Выбирает следующую строку набора результатов запросов, возвращая одиночную последовательность или None, когда больше нет доступных данных. Исключительная ситуация Error (или ее подкласс) произойдет, если предыдущее обращение к executeXXX() не производило никакого набора результатов.
fetchmany([size=cursor.arraysize])
Выбирает следующую строку набора результатов запросов, возвращая последовательность последовательностей (например, список tuples). Пустая последовательность будет возвращена, когда больше нет доступных строк. Число строк, которое надо выбрать за обращение, определено параметром. Если это не задано, arraysize курсора определяет число строк, которые будут выбраны. Метод должен пробовать выбирать так много строк, как уаазано параметром. Если это невозможно из-за определенного числа строк, меньшее количество строк может быть возвращено.

Исключительная ситуация Error (или ее подкласс) произойдет, если предыдущее обращение к executeXXX() не производило никакого набора результатов.

Обратите внимание, что имеются сложности с эффективностью, включаемые с параметром размера. Для достижения оптимальной эффективности, обычно самое лучшее использовать arraysize.

fetchall()
Выбирает все оставшиеся строки результата запроса, возвращая их как последовательность последовательностей (например, список tuples). Обратите внимание, что атрибут arraysize курсора может воздействовать на эффективность этой операции. Исключительная ситуация Error (или ее подкласс) произойдет, если предыдущее обращение к executeXXX() не производило никакого набора результатов.
nextset()
Этот метод факультативный, поскольку не все базы данных поддерживают многократные наборы результатов.

Этот метод будет переводить курсор к следующему доступному набору, отбрасывая любые остающиеся строки из текущего (актуального) набора.

Если не имеется больше никаких наборов, метод возвращает None. Иначе он возвращает значение true, и последующие обращения к методам выборки возвратят строки из следующего набора результатов.

Исключительная ситуация Error (или ее подкласс) произойдет, если предыдущее обращение к executeXXX() не производило никакого набора результатов.

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

arraysize
Этот атрибут для чтения-записи определяет число строк, которое надо выбрать с помощью fetchmany() за раз. Значение по умолчанию 1 (выбрать одиночную строку результатов)

Реализации должны отслеживать это значение применительно к методу fetchmany(), но никто не запрещает реально работать с базой данных каким-либо иным способом. Это может также использоваться в реализации метода executemany().

setinputsizes(sizes)
Это может использоваться перед обращением для executeXXX() к предопределенным областям памяти для параметров операции. sizes определен как последовательность: один элемент для каждого входного параметра. Элемент должен быть Type Object, который соответствует вводу, который будет использоваться, или это должно быть целым числом, определяющим максимальную длину параметра строки. Если элемент равен None, то никакая предопределенная область памяти не будет зарезервирована для этого столбца (это полезно, чтобы избегать предопределенных областей для больших вводов). Метод не является обязательным для использования и реализации.
setoutputsize(size[,column])
Устанавливает размер буфера столбца для выборок больших столбцов (например, LONG, BLOB и им подобных). Столбец определен как индекс в последовательности результатов. Отсутствие определения column установит заданный по умолчанию размер для всех больших столбцов в курсоре. Метод не является обязательным для использования и реализации.

5.7.4 Типы конструкторов и объектов

Многие базы данных должны иметь ввод в специфическом формате для связывания с входными параметрами операции. Например, если ввод предназначен для столбца DATE, то это будет связано с базой данных в специфическом формате строки. Подобные проблемы существуют для столбцов "Row ID" или больших двоичных элементов (например, столбцов blob или RAW). Это представляет проблемы для Python, начиная с параметров для метода без контроля типов executeXXX(). Когда модуль базы данных видит строковый объект, он не знает сходу, как с ним быть.

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

Атрибут description объекта курсора возвращает информацию относительно каждого из столбцов результата запроса. Здесь type_code должен быть равен одному из Type Objects, определенных ниже. Эти самые Type Objects могут быть равны больше, чем одному коду типа (например, DATETIME может быть равен кодам типа для столбцов даты, времени и метки времени).

Модуль экспортирует следующие конструкторы:

Date(year,month,day)
Эта функция создает объект, хранящий значение даты.
Time(hour,minute,second)
Эта функция создает объект, хранящий значение времени.
Timestamp(year,month,day,hour,minute,second)
Эта функция создает объект, хранящий значение метки времени.
DateFromTicks(ticks)
Эта функция создает объект, хранящий значение даты с данного значения импульсов сигнала времени (число секунд, начиная с epoch, согласно стандартному модулю Python time).
TimeFromTicks(ticks)
Эта функция создает объект, хранящий значение времени с данного значения импульсов сигнала времени (число секунд, начиная с epoch, согласно стандартному модулю Python time).
TimestampFromTicks(ticks)
Эта функция создает объект, хранящий значение метки времени с данного значения импульсов сигнала времени (число секунд, начиная с epoch, согласно стандартному модулю Python time).
Binary(string)
Эта функция создает объект, способный хранить строковое двоичное значение типа long.
STRING
Этот объект используется, чтобы описать столбцы в базе данных, которые являются основанными на строках (например, типа CHAR).
BINARY
Этот объект используется, чтобы описать двоичные (long) столбцы в базе данных (например, LONG, RAW, BLOB).
NUMBER
Этот объект используется, чтобы описать числовые столбцы в базе данных.
DATETIME
Этот объект используется, чтобы описать столбцы даты/времени в базе данных.
ROWID
Этот объект используется, чтобы описать "Row ID" столбец в базе данных.

SQL-значение NULL представляется на вводе и выводе как Python None.

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

5.7.5 Хитрости в реализации

  • Привилегированные объектные типы для объектов даты/времени определены в пакете mxDateTime ( http://starship.python.net/~lemburg/mxDateTime.html). Это обеспечивает все необходимые конструкторы и методы на уровнях Python и C.
  • Привилегированный объектный тип для объектов Binary является буферным типом, доступный в стандартном Python, начиная с версии 1.5.2. Подробности ищите в документации на Python и в дистрибутиве его исходников (файлы Include/bufferobject.h и Objects/bufferobject.c).
  • Имеется типовая реализация конструкторов для даты/времени, делегирующая работу универсальным конструкторам на основе Unix-импульсов сигнала времени:
    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])
    
  • Этот класс Python позволяет выполнять вышеупомянутые объекты типа даже при том, что поле кода типа описания выдает много значений для type object:
    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
    
    Возникающий в результате объект сравнивается со всеми значениями, переданными конструктору.
  • Имеется отрывок кода на Python, который реализует иерархию исключительных ситуаций, определенную выше:
    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
    
    На C Вы можете использовать API PyErr_NewException(fullname,base,NULL), чтобы создать объекты исключительной ситуации.

5.7.6 Изменения при переходе с версии 1.0 на 2.0

Python Database API 2.0 представляет несколько важных нововведений по сравнению с версией 1.0. Некоторые из этих изменений делают невозможным применять старые скрипты с новой версией DB API.

  • Потребность в отдельном dbi модуле была ликвидирована, и функциональные возможности, объединены непосредственно в интерфейс модуля.
  • Новые конструкторы и Type Objects были добавлены для значений даты/времени, RAW Type Object переименован в BINARY. Возникающий в результате набор должен покрыть все базисные типы данных, обычно присутствующие в современных базах данных на SQL.
  • Были добавлены новые константы (apilevel, threadlevel, paramstyle) и методы (executemany, nextset), чтобы обеспечить лучшее взаимодействие с разными базами данных.
  • Семантика метода callproc(), нужная чтобы вызывать хранимые процедуры, теперь ясно определена.
  • Определение значения возврата execute() изменилось. Раньше значение возврата было основано на типе инструкции SQL (что было не так-то просто реализовать), теперь же оно неопределенно, используйте более гибкий атрибут rowcount вместо этого. Модули могут использовать старый стиль значений возврата, но они больше не переданы под мандат спецификацией и должны рассматриваться как зависимый интерфейс базы данных.
  • Классы основных исключительных ситуаций были включены в спецификацию. Можно расширить иерархию исключительных ситуаций, определенную в этой спецификации, подклассифицируя определенные классы исключительных ситуаций.

Известные проблемы

Хотя спецификация версии 2.0 разъясняет много вопросов, которые были оставлены открытыми в версии 1.0, некоторые все еще остаются проблемами:

  • Определение полезного значения возврата для nextset() для случая, когда новый набор результат доступен.
  • Создание числового типа с фиксированной точкой для использования в качестве типа для пересчета чисел с минимальными потерями.

Замечания

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

Модуль использует метод __getitem__ объекта параметров, чтобы отобразить позиции (целые числа) или имена (строки) к значениям параметра. Это учитывает последовательности и отображения, которые нужно использовать как ввод.

Значение передается базе данных напрямую. В практических условиях это означает, что входное значение непосредственно используется как значение в операции. Пользователь не должен требоваться, чтобы экранировать значение так, чтобы оно могло использоваться: значение должно быть равно фактическому параметру для базы данных.

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

Поиск

 

Найди своих коллег!