API-специфікація баз даних мови Python, версія 2.0 (Database API Specification 2.0), Різне, Програмування, статті

Python.org, переклад: Intersoft Lab

Цей API був визначений для заохочення подібності між модулями Python, використовуваними для доступу до баз даних. Таким чином ми сподіваємося досягти відповідності, яке призведе до більш зрозумілим модулям, коду, який в цілому легше переносимо між базами даних і більш широкому спектру можливостей мови Python з доступу до баз даних.

Специфікація інтерфейсу складається з кількох розділів:

Інтерфейс модуля
Об’єкти з’єднання
Об’єкти курсора
Об’єкти типу та конструктори
Поради щодо реалізації
Основні зміни у версії 2.0 щодо версії 1.0

Коментарі і питання по цій специфікації можуть бути направлені на адресу Спеціальної групи з доступу до баз даних з Python.

За додатковою інформацією про доступ до баз даних з Python і про наявних пакетах звертайтеся до Керівництву по базах даних на www.python.org.

Цей документ описує Python Database API Specification 2.0. Попередня версія 1.0 все ще доступна для довідки. Заохочується використання останньої версії специфікації в якості основи для нового інтерфейсу програмістами, які пишуть пакети.

Інтерфейс модуля

Доступ до бази даних реалізується за допомогою об’єктів з’єднання (connection objects). Модуль повинен надавати для них наступний конструктор:

connect(Параметри. ..)
Конструктор для створення з’єднання з базою даних. Повертає Об’єкт з’єднання. Має ряд параметрів, які залежать від бази даних. [1]

Повинні бути визначені такі глобальні змінні модуля:

apilevel
Строкова константа, що позначає підтримуваний рівень DB API. В даний час допускаються тільки рядки '1.0' і '2.0'. Якщо не задана, передбачається рівень Database API 1.0.
threadsafety
Целочисленная константа, що позначає рівень нітебезопасності, підтримуваний даним інтерфейсом. Можливі значення:
0 = Модуль не може розділятися нитками.
1 = Нитки можуть розділяти модуль, але не з’єднання.
2 = Нитки можуть розділяти і модуль, і з’єднання.
3 = Нитки можуть розділяти модуль, з’єднання і курсори. Поділ у вищевказаному контексті означає, що дві нитки можуть використовувати ресурс, не використовуючи зовнішній об’єкт синхронізації (mutex) для блокування. Зауважте, що ви не завжди можете забезпечити нітебезопасность для зовнішніх ресурсів, керуючи доступом за допомогою семафора: ресурс може використовувати глобальні змінні або інші зовнішні ресурси, що знаходяться поза вашого контролю.
paramstyle Строкова константа, що позначає тип форматування маркера параметра, очікуваний інтерфейсом. Можливі значення [2]:
'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 (визначеного в модулі exceptions).
Error Виняток, що є базовим класом всіх інших винятків, пов’язаних з помилками. Ви можете використовувати його для перехоплення всіх винятків за допомогою єдиного твердження ‘except’. Попередження не розглядаються як помилки і тому не повинні використовувати цей клас в якості базового. Цей клас має бути похідним від класу Python StandardError (визначеного в модулі exceptions).
InterfaceError Виняток збуджується для помилок, що відносяться до інтерфейсу бази даних в більшій мірі, ніж до самої бази. Повинно бути похідним від класу Error.
DatabaseError Виняток збуджується для помилок, що відносяться до бази даних. Воно повинно бути підкласом класу Error.
DataError Виняток збуджується для помилок, що відносяться до проблем з робочою даними, такими як поділ на нуль, вихід величини за межі допустимих значень і т.д. Повинно бути похідним від класу DatabaseError.
OperationalError Виняток збуджується для помилок, що відносяться до операцій бази даних, не обов’язково перебувають під контролем програміста, наприклад, несподіваний обрив з’єднання, не знайдено ім’я джерела даних, неможливо обробити транзакцію, помилка розподілу пам’яті в процесі обробки і т.д. Повинно бути похідним від класу DatabaseError.
IntegrityError Виняток порушується у разі, коли порушена посилальна цілісність бази даних, наприклад, спроба посилання на неіснуючу зовнішню запис. Повинно бути похідним від класу DatabaseError.
InternalError Виняток порушується у разі, якщо база даних виявляє внутрішню помилку, наприклад, курсор більше не є допустимим, транзакція не синхронізована і т.д. Повинно бути похідним від класу DatabaseError.
ProgrammingError Виняток порушується у разі помилок програмування, наприклад, таблиця не знайдено або вже існує, синтаксична помилка в реченні SQL, задано невірне число параметрів і т.д. Повинно бути похідним від класу DatabaseError.
NotSupportedError Виняток порушується у разі використання виклику API, не підтримуваного базою даних, наприклад, запит. Rollback () до з’єднання, не підтримує транзакції або транзакції у якого відключені. Повинно бути похідним від класу DatabaseError.

Ось схема успадкування винятків:

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

Примітка: Значення цих винятків не визначені. Вони повинні чітко підказувати користувачу, що саме пішло не так.

Об’єкти з’єднання

Об’єкти з’єднання повинні реагувати на такі виклики:

close() Закрити з’єднання зараз (а не при виклику __ del__). З’єднання буде невживаних з цього моменту і далі, якщо яка-небудь операція спробує скористатися цим з’єднанням, буде порушено виняток Error (або його підклас). Те ж саме застосовується і до всіх об’єктів курсора, які намагаються використовувати це з’єднання.
commit() Завершити яку незавершену транзакцію в базі даних. Зауважте, що якщо база підтримує автоматичну фіксацію, у вихідному положенні вона повинна бути відключена. Інтерфейс може надавати метод для включення автофіксації.
Модулі баз даних, не підтримують транзакції, повинні реалізовувати цей метод у вигляді заглушки.
rollback() Цей метод не є обов’язковим, оскільки не всі бази даних забезпечують підтримку транзакцій.[3]
У разі, якщо база даних забезпечує підтримку транзакцій, цей метод змушує базу даних відкотити до початку незавершену транзакцію. Закриття з’єднання без попередньої явної фіксації змін призведе до неявному відкоту.
cursor() Повернути новий Об’єкт курсора, Використовуючи з’єднання. Якщо база не забезпечує підтримку концепції курсора, модуль повинен емулювати курсори, використовуючи інші засоби в межах, необхідних для цієї специфікації. [4]
Об’єкти курсора

Ці об’єкти представляють курсор бази даних, що використовується для управління контекстом операції вибірки.

Об’єкти курсора повинні підтримувати такі методи і атрибути:
description Цей read-only атрибут являє собою послідовність семизначних послідовностей. Кожна з таких послідовностей містить інформацію, що описує одну колонку результату: (name, type_code, display_size, internal_size, precision, scale, null_ok). Цей атрибут буде приймати значення None для операцій, не повертають рядка або у випадку, коли курсор ще не виконав операцію за допомогою методу executeXXX(). Type_code може інтерпретуватися шляхом порівняння його з Об’єктами типу, Визначеними в наступному розділі.
rowcount Цей read-only атрибут визначає число рядків вибране (для пропозицій DQL зразок select) Або порушене (для модифікуючих пропозицій DML зразок update або insert) Останнім викликом executeXXX(). Цей атрибут приймає значення -1 у випадку, якщо над курсором не виконаний жоден executeXXX() або якщо інтерфейс не може визначити кількість рядків в останню операцію.[7]
callproc(Ім’я процедури [, параметри]) Цей метод необов’язковий, оскільки не всі бази даних підтримують збережені процедури.[3] Викликати збережену процедуру з заданим ім’ям. Послідовність параметрів повинна містити один вхід для кожного аргументу, очікуваного процедурою. Результат виклику повертається у вигляді модифікованої копії вихідної послідовності. Input-параметри залишаються недоторканими, output і input / output параметри можуть бути замінені новими значеннями. Процедура може також забезпечувати на виході результуюче безліч. Воно потім повинно бути доступно через стандартні методи fetchXXX().
close() Закрити курсор (зараз, а не при виклику __ del__). З моменту виклику і далі курсор стає невживаних; в разі спроби звернутися до деякої операції курсора, збуджується виключення Error (Або підклас).
execute(Операція [, параметри]) Підготувати і виконати операцію бази даних (запит або команду). Параметри можуть забезпечуватися в вигляді послідовності або словника і будуть прив’язані до змінних в операції. Змінні задаються в нотації, специфічної для бази даних (детально див атрибут модуля paramstyle). [5] Посилання на операцію буде зберігатися курсором. Якщо такий же об’єкт операції передається знову, курсор може оптимізувати свою поведінку. Це найбільш ефективно для алгоритмів, в яких багато разів використовуються одна і та ж операція, але з прив’язкою різних параметрів. Для максимальної ефективності при повторному використанні операції, найкраще скористатися методом setinputsizes () для того, щоб заздалегідь задати типи і розміри параметрів. Для параметра допустимо невідповідність заздалегідь певної інформації; реалізація повинна компенсувати це, можливо, з деякою втратою ефективності. Параметри можуть бути також визначені як список кортежів, наприклад, для вставки безлічі рядків в рамках однієї операції, але це не заохочується: замість цього слід скористатися executemany(). Значення, що повертаються не визначені.
executemany(Операція, seq_of_parameters) Підготувати операцію бази даних (запит або команду) і потім виконати її для всіх послідовностей або словників, знайдених в послідовності параметрів seq_of_parameters. Модулі вільні у реалізації цього методу або з використанням множинних визовово методу execute (), або з використанням масивних операцій для того, щоб змусити базу даних обробити послідовність цілком за один виклик. Примітки, дані для execute(), Застосовні також і до цього методу. Значення, що повертаються не визначені.
fetchone() Вибирає наступний рядок з результуючого безлічі – результату запиту, повертаючи одиночну послідовність, або None у разі, коли даних більше немає. [6] Виняток Error (Або підклас) порушується, якщо попередній виклик executeXXX() не повернув результуючого безлічі, або ще не було жодного такого виклику.
fetchmany([Розмір = cursor.arraysize]) Вибирає наступний набір рядків з результату запиту, повертаючи послідовність послідовностей (наприклад, список кортежів). Порожня послідовність повертається, якщо більше немає ніяких рядків. Число рядків для вибірки за один виклик визначається параметром. Якщо параметр не заданий, число рядків для вибірки визначає атрибут курсора arraysize. Цей метод повинен спробувати обрати стільки рядків, скільки вказано в параметрі. Якщо така кількість рядків недоступно, може бути повернуто менше число рядків. Виняток Error (Або підклас) порушується, якщо попередній виклик executeXXX() не повернув результуючого безлічі, або ще не було жодного такого виклику. Позначте, що є деякі міркування, пов’язані з параметром розміру. Для досягнення оптимальної продуктивності зазвичай найкраще користуватися атрибутом arraysize. Якщо використовується параметр розміру, то краще, щоб він зберігав одну і ту ж величину від одного виклику fetchmany() до наступного.
fetchall() Вибирає всі (залишилися) рядки результату запиту, повертаючи їх у вигляді послідовності послідовностей (наприклад, списку кортежів). Зауважте, що атрибут курсора arraysize може впливати на продуктивність цієї операції. Виняток Error (Або підклас) порушується, якщо попередній виклик executeXXX() не повернув результуючого безлічі, або ще не було жодного такого виклику.
nextset(). Цей метод не є обов’язковим, оскільки не всі бази даних підтримують кілька результуючих множин. [3] Цей метод змусить курсор перейти на наступне наявне безліч, ігноруючи всі залишилися рядки поточного множини. Якщо більше множин немає, метод повертає None. Інакше він повертає значення істинності, і наступні звернення до методів вибірки повертатимуть рядки з наступного результуючого безлічі. Виняток Error (Або підклас) порушується, якщо попередній виклик executeXXX() не повернув результуючого безлічі, або ще не було жодного такого виклику.
arraysize Цей read / write атрибут визначає число рядків, які обирають fetchmany() за один раз. За замовчуванням має значення 1, що означає вибірку одного рядка за один раз. Реалізації повинні дотримуватися цього значення в тому, що стосується методу fetchmany(), Однак вони мають повне право вибирати по одному рядку за раз при взаємодії з базою даних. Цей атрибут може бути також використаний в реалізації executemany().
setinputsizes(sizes) Може використовуватися перед викликом executeXXX() для попереднього визначення областей пам’яті під параметри операції. Параметр sizes (Розміри) визначено як послідовність – один елемент для кожного вхідного параметра. Елемент повинен бути об’єктом типу (Type Object, наприклад, IntType), відповідним типом параметра, або цілим числом, визначальним максимальну довжину строкового параметра. Якщо елемент має значення None, Під цей стовпець не буде зарезервовано заздалегідь визначеної області пам’яті (це полеено, щоб уникнути виділення областей для великих вводів). Цей метод може використовуватися перед викликом методу executeXXX(). Реалізації можуть залишити цей метод заглушкою, а користувачі можуть не використовувати його.
setoutputsize(Розмір [, стовпець]) Встановлює розмір буфера стовпця для вибірки великих стовпців (наприклад, LONG, BLOB та ін.) Стовпець задається як індекс (номер стовпця) в Результуюча множині. Якщо стовпець не заданий, встановлюється розмір за умовчанням для всіх великих стовпців в курсорі. Цей метод може використовуватися перед викликом методу executeXXX(). Реалізації можуть залишити цей метод заглушкою, а користувачі можуть не використовувати його.
Об’єкти типу та конструктори

Багато баз даних вимагають вхідних даних у певному форматі для прив’язки до input-параметрами операцій. Наприклад, якщо дані призначені для стовпця типу DATE, вони повинен бути підготовлені для бази даних у певному строковому форматі. Такі ж проблеми існують для стовпців “Row ID” або великих бінарних елементів (наприклад, blob’ов або стовпців RAW). Це становить проблему для Python, оскільки параметри методу executeXXX() НЕ типізовані. Коли модуль бази даних бачить строковий об’єкт Python, він не знає, чи потрібно його прив’язувати як простий символьний стовпець (CHAR), як необроблений бінарний елемент (BINARY) або як дату (DATE).

Для подолання цієї проблеми модуль повинен забезпечувати описані нижче конструктори для створення об’єктів, які можуть зберігати спеціальні значення. Коли такий об’єкт передется методам курсора, модуль може визначити правильний тип вхідного параметра і прив’язати його відповідним чином.

Атрибут об’єкта курсора description повертає інформацію про кожного з стовпців результату запиту. Код типу type_code повинен бути перевірений на рівність одному з Об’єктів типу, описаних нижче. Об’єкти типу можуть бути рівні більш ніж одному коду типу (наприклад, DATETIME може дорівнювати кодами типу для стовпців дати, часу і тимчасової мітки; докладно см. Поради щодо реалізації, Дані нижче).

Модуль експортує наступні конструктори і одноелементні множини:

Date(Рік, місяць, день) Ця функція створює об’єкт, що містить значення дати.
Time(Година, хвилина, секунда) Ця функція створює об’єкт, що містить значення часу.
Timestamp(Рік, місяць, день, година, хвилина, секунда) Ця функція створює об’єкт, що містить значення тимчасової мітки.
DateFromTicks(Відліки) Ця функція створює об’єкт, що містить значення дати, з заданої кількості відліків (ticks) (числа секунд з початку епохи; детально див документацію по стандартному модулю time мови Python).
TimeFromTicks(Відліки) Ця функція створює об’єкт, що містить значення часу, з заданої кількості відліків (ticks) (числа секунд з початку епохи; детально див документацію по стандартному модулю time мови Python).
TimestampFromTicks(Відліки) Ця функція створює об’єкт, що містить значення тимчасової мітки, з заданої кількості відліків (ticks) (числа секунд з початку епохи; детально див документацію по стандартному модулю time мови Python).
BINARY(Рядок) Ця функція створює об’єкт, здатний утримувати бінарне (довге) строкове значення.
STRING Цей об’єкт типу використовується для опису строкових стовпців у базі даних (наприклад, CHAR).
BINARY Цей об’єкт типу використовується для опису (довгих) бінарних стовпців у базі даних (наприклад, LONG, RAW, BLOB).
NUMBER Цей об’єкт типу використовується для опису числових стовпців в базі даних.
DATETIME Цей об’єкт типу використовується для опису в базі даних стовпців дата / час.
ROWID Цей об’єкт типу використовується для опису в базі даних стовпців “Row ID”.

NULL-значення SQL представляються за допомогою None при введенні і виведенні.

Примітка: Використання відліків Unix при взаємодії з базою даних може створити проблеми через обмеженість спектра описуваних ними дат.

Поради щодо реалізації

Основні зміни у версії 2.0 щодо версії 1.0

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().

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*