Главная страница

справочник по Python. мм isbn 9785932861578 9 785932 861578


Скачать 4.21 Mb.
Названиемм isbn 9785932861578 9 785932 861578
Анкорсправочник по Python
Дата08.05.2022
Размер4.21 Mb.
Формат файлаpdf
Имя файлаBizli_Python-Podrobnyy-spravochnik.440222.pdf
ТипСправочник
#518195
страница30 из 82
1   ...   26   27   28   29   30   31   32   33   ...   82
Глава
17
.
Доступ к базам данных
В этой главе описываются программные интерфейсы, которые использу- ются программами на языке Python с реляционными базами данных и с базами данных, подобных хеш-таблицам. В отличие от других глав, где описываются модули из стандартной библиотеки, в этой главе будут за- тронуты сторонние расширения. Например, если вам потребуется органи- зовать доступ к базе данных MySQL или Oracle, для начала вам придется загрузить модуль стороннего расширения. Но этот модуль, в свою очередь, будет следовать основным соглашениям, которые описываются здесь.
Прикладной интерфейс доступа
к реляционным базам данных
Для обеспечения доступа к реляционным базам данных сообществом раз- работчиков Python был выработан стандарт, известный как «Python Da-
Python был выработан стандарт, известный как «Python Da- был выработан стандарт, известный как «Python Da-
Python Da-
Da-
Da- tabase API Specification V2.0», или PEP 249 (формальное описание можно найти по адресу http://www.python.org/dev/peps/pep-249/). Модули для до- ступа к определенным базам данных (таким как MySQL, Oracle и другие) следуют этому стандарту, но могут добавлять дополнительные возможно- сти. В этом разделе рассматриваются самые основные элементы интерфей- са, необходимые большинству приложений.
На верхнем уровне прикладного интерфейса доступа к базам данных определяется множество функций и классов, обеспечивающих соединение с сервером баз данных, выполнение запросов SQL и получение результатов.
Для этих целей используются два основных класса: Connection, который управляет соединением с базой данных, и Cursor, используемый для выпол- нения запросов.
Соединения
Каждый модуль доступа к базам данных предоставляет функцию con- nect(
parameters)
, позволяющую установить соединение с базой данных.

376
Глава 17. Доступ к базам данных
Т
очное количество аргументов зависит от базы данных, однако в их число обычно входят: имя источника данных, имя пользователя, пароль, имя хо- ста и имя базы данных. Как правило, все эти значения передаются в виде именованных аргументов dsn, user, password, host и database соответственно.
Поэтому вызов connect() может выглядеть, как показано ниже:
connect(dsn=”hostname:DBNAME”,user=”michael”,password=”peekaboo”)
В случае успеха функция возвращает объект класса Connection. Экземпляр
c
класса Connection обладает следующими методами:
c.close()
Закрывает соединение с сервером.
c.commit()
Подтверждает все незавершенные транзакции в базе данных. Если база данных поддерживает механизм транзакций, любые изменения в базе дан- ных вступят в силу только после вызова этого метода. Если база данных не поддерживает транзакции, этот метод ничего не делает.
c.rollback()
Откатывает все изменения в базе данных до момента, когда были запуще- ны какие-либо незавершенные транзакции. Иногда этот метод использует- ся при работе с базами данных, не поддерживающими транзакции, чтобы отменить любые изменения, произведенные в них. Например, если в про- цессе изменения данных в базе возникло исключение, можно воспользо- ваться этим методом, чтобы отменить изменения, произведенные до появ- ления исключения.
c.cursor()
Создает новый курсор, экземпляр класса Cursor, использующий соедине- ние. Курсор – это объект, который используется для выполнения запросов
SQL и получения результатов. Об этом рассказывается в следующем раз- и получения результатов. Об этом рассказывается в следующем раз- деле.
Курсоры
Чтобы выполнить какие-либо операции в базе данных, сначала необходи- мо создать объект соединения c, а затем вызовом метода c.cursor() создать объект класса Cursor. Экземпляр cur класса Cursor обладает множеством стандартных методов и атрибутов, которые используются для выполнения запросов:
cur.callproc(procname [, parameters])
Вызывает хранимую процедуру с именем procname. В аргументе parameters передается последовательность значений, которые будут переданы храни- мой процедуре в виде ее аргументов. Результатом этой функции является последовательность с тем же количеством элементов, что и в последова- тельности parameters. Эта последовательность является копией последова- тельности parameters, где значения любых выходных аргументов замеща- ются значениями, полученными в результате выполнения хранимой про-

Прикладной интерфейс доступа к реляционным базам данных
377
цедуры. Кроме того, если процедура выводит некоторый набор данных, его можно получить с помощью методов fetch*(), описываемых ниже.
cur.close()
Закрывает курсор, предотвращая возможность выполнения каких-либо дальнейших операций с его помощью.
cur.execute(query [, parameters])
Выполняет запрос или команду query в базе данных. В аргументе query пе- редается строка, содержащая команду (обычно на языке SQL), а в аргумен-
SQL), а в аргумен-
), а в аргумен- те parameters – либо последовательность, либо отображение со значениями переменных, используемых в строке запроса query (об этом рассказывается в следующем разделе).
cur.executemany(query [, parametersequence])
Многократно выполняет запрос или команду query. В аргументе query пере- дается строка запроса, а в аргументе parametersquence – последовательность групп параметров. Каждый элемент этой последовательности должен быть объектом последовательности или отображения, который можно было бы передать методу execute(), описанному выше.
cur.fetchone()
Возвращает следующую запись из набора данных, полученного вызовом метода execute() или executemany(). Как правило, результатом является список или кортеж значений различных столбцов в наборе данных. После извлечения последней записи из набора возвращается None. В случае отсут-
В случае отсут- ствия набора данных или в случае, когда предыдущая операция не вернула ничего, возбуждается исключение.
cur.fetchmany([size])
Возвращает последовательность записей из полученного набора данных (то есть список кортежей). В аргументе size указывается количество записей, которые требуется вернуть. При вызове без аргумента в качестве значения по умолчанию используется значение атрибута cur.arraysize. Фактическое число возвращаемых записей может оказаться меньше запрошенного.
Если ранее были выбраны все записи, возвращается пустая последователь- ность.
cur.fetchall()
Возвращает последовательность всех записей (то есть список кортежей), оставшихся в полученном наборе данных.
cur.nextset()
Пропускает все оставшиеся записи в текущем наборе данных и переходит к следующему набору (если имеется). Если следующего набора данных не существует, возвращает None; в противном случае возвращает True, а после- дующие операции fetch*() будут возвращать данные из нового набора.
cur.setinputsize(sizes)
Сообщает курсору информацию о параметрах, которые будут передаваться в последующих вызовах методов execute*(). В аргументе sizes передается

378
Глава 17. Доступ к базам данных последовательность объектов типов (описывается чуть ниже) или целых чисел, которые обозначают максимальную ожидаемую длину строки для каждого параметра. Эта информация используется объектом курсора для выделения буферов в памяти, которые будут использоваться при создании запросов и команд, посылаемых базе данных. Это позволяет повысить ско- рость выполнения последующих операций execute*().
cur.setoutputsize(size [, column])
Устанавливает размер буфера для определенного столбца в возвращае- мом наборе данных. В аргументе column передается целочисленный индекс поля в записи, а в аргументе size – количество байтов. Обычно этот метод используется, чтобы установить ограничения для столбцов, которые мо- гут содержать большие объемы информации, таких как строки, объекты
BLOB и объекты LONG, перед тем, как вызывать методы execute*(). Если аргумент column опущен, ограничение size устанавливается для всех столб- цов в возвращаемом наборе данных.
Курсоры обладают рядом атрибутов с информацией о текущем наборе дан- ных и о самом курсоре.
cur.arraysize
Целое число, которое используется методом fetchmany() как значение по умолчанию. Это значение может отличаться в разных модулях доступа к базам данных и изначально может устанавливаться равным «оптималь- ному», с точки зрения модуля, значению.
cur.description
Последовательность кортежей с информацией о каждом столбце в текущем наборе данных. Каждый кортеж имеет вид (name, type_code, display_size,
internal_size, precision, scale, null_ok)
. Первое поле всегда содержит имя столбца. Значение в поле type_code может использоваться в операциях срав- нивания с типами объектов, о которых рассказывается в разделе «Типы объектов». Другие поля в кортеже могут иметь значение None, если они не имеют смысла для столбца.
cur.rowcount
Количество записей в наборе данных, полученном в результате последнего вызова одного из методов execute*(). Значение -1 означает, что либо набор данных в результате отсутствует, либо количество записей не может быть определено.
Хотя это и не оговаривается спецификацией, тем не менее реализация классов Cursor в большинстве модулей доступа к базам данных обеспечива- ют поддержку протокола итераций. То есть, чтобы обойти все записи в на- боре данных, полученном в результате последнего вызова одного из мето- дов execute*(), можно использовать инструкцию, такую как for row in cur:.
Ниже приводится простой пример, демонстрирующий, как некоторые из этих операций могут использоваться при работе с модулем sqlite3 доступа к базе данных, который входит в состав стандартной библиотеки:

Прикладной интерфейс доступа к реляционным базам данных
379
import sqlite3
conn = sqlite3.connect(“dbfile”)
cur = conn.cursor()
ёё
# Пример простого запроса cur.execute(“select name, shares, price from portfolio where account=12345”)
ёё
# Обход результатов в цикле while True:
row = cur.fetchone()
if not row: break
# Обработать запись name, shares, price = row
...
ёё
# Альтернативный подход (с использованием итераций)
cur.execute(“select name, shares, price from portfolio where account=12345”)
for name, shares, price in cur:
# Обработать запись
...
Формирование запросов
Критически важным этапом при использовании прикладного интерфейса доступа к базам данных является формирование строки запроса SQL, ко-
SQL, ко-
, ко- торая передается методам execute*() объектов курсоров. Отчасти проблема заключается в необходимости вставить в строку запроса параметры, кото- рые вводятся пользователем. Например, можно было бы написать такой программный код:
symbol = “AIG”
account = 12345
ёё
cur.execute(“select shares from portfolio where name=’%s’ and account=%d” %
(symbol, account))
Этот прием «действует», тем не менее никогда не следует вручную форми- ровать запросы с помощью строковых операций, как это сделано в дан- ном примере. В противном случае появляется уязвимость к атакам типа
«инъекция SQL», которой может воспользоваться злоумышленник, чтобы выполнить произвольные инструкции на сервере баз данных. Например, в предыдущем примере злоумышленник мог бы передать в параметре sym- bol значение “EVIL LAUGH’; drop table portfolio;--” которое, очевидно, приво- дит совсем не к тем результатам, которые вы могли бы ожидать.
Все модули доступа к базам данных предоставляют собственные механиз- мы подстановки значений. Например, вместо того, чтобы формировать за- прос целиком, как было показано выше, то же самое можно было бы сде- лать иначе:
symbol = “AIG”
account = 12345
ёё
cur.execute(“select shares from portfolio where name=? and account=?”,
(symbol, account))

380
Глава 17. Доступ к базам данных
Здесь символы подстановки ‘?’ благополучно замещаются значениями из кортежа (symbol, account).
К сожалению, не существует единого соглашения о правилах оформления символов подстановки между различными модулями доступа к базам дан- ных. При этом в каждом модуле может быть задана переменная paramstyle, которая определяет формат параметров в запросах, замещаемых фактиче- скими значениями. Ниже перечислены возможные значения этой перемен- ной:
Формат параметра
Описание
‘qmark’
Параметры обозначаются знаком вопроса, где каждый символ ? в запросе замещается очередным элементом по- следовательности. Например: cur.execute(“... where name=? and account=?”, (symbol, account))
. Значения параметров передаются в виде кортежа.
‘numeric’
Параметры обозначаются числами, где параметр :n заме- заме- щается значением с индексом n. Например: cur.execute(“... where name=:0 and account=:1”,(symbol, account))
‘named’
Именованные параметры, где параметр :name замещается именованным значением. В этом случае значения параме- тров должны передаваться в виде отображения. Например:
cur.execute(“... where name=:symbol and account=:account”,
{‘symbol’:symbol, ‘account’: account})
.
‘format’
Параметры обозначаются в стиле функции printf, в виде спецификаторов формата, таких как %s, %d и так далее. На- пример: cur.execute(“... where name=%s and account=%d”, (sym- bol, account))
‘pyformat’
Расширенный набор кодов формата в стиле языка Python, таких как %(name)s. Напоминает формат ‘named’. Значения параметров должны передаваться в виде отображения, а не в виде кортежа.
Типы объектов
При работе с базами данных встроенные типы, такие как целые числа и строки, обычно отображаются в эквивалентные типы, используемые ба- зой данных. Однако все усложняется, когда приходится работать с такими данными, как даты, двоичные данные, и другими специальными типами.
Чтобы упростить отображение данных этих типов, модули доступа к базам данных реализуют набор функций-конструкторов, позволяющих созда- вать объекты различных типов.
Date(year, month, day)
Создает объект, представляющий дату.
Time(hour, minute, second)
Создает объект, представляющий время.

Прикладной интерфейс доступа к реляционным базам данных
381
Timestamp(year, month, day, hour, minute, second)
Создает объект, представляющий отметку времени.
DateFromTicks(ticks)
Создает объект, представляющий дату, из значения системного времени.
В аргументе ticks передается количество секунд, возвращаемое такими функциями, как time.time().
TimeFromTicks(ticks)
Создает объект, представляющий время, из значения системного времени.
TimestampFromTicks(ticks)
Создает объект, представляющий отметку времени, из значения системно- го времени.
Binary(s)
Создает объект, представляющий двоичные данные, из строки байтов s.
В дополнение к этим конструкторам в модулях могут объявляться следую- щие типы объектов. Эти типы объектов предназначены для проверки типа, указанного в поле type_code атрибута cur.description, который содержит ин- формацию о содержимом текущего набора данных.
Тип объекта
Описание
STRING
Символьные или текстовые данные
BINARY
Двоичные данные, такие как BLOB
NUMBER
Числовые данные
DATETIME
Дата и время
ROWID
Идентификатор записи
Обработка ошибок
Модули доступа к базам данных объявляют исключение Error верхнего уровня, которое служит базовым классом для всех остальных исключений.
Ниже приводится перечень более специализированных исключений, име- ющих отношение к ошибкам, возникающим при работе с базами данных:
Исключение
Описание
InterfaceError
Ошибки, связанные с неправильным использованием ин- терфейса к базе данных, но не с самой базой данных.
DatabaseError
Ошибки, имеющие отношение к самой базе данных.
DataError
Ошибки, связанные с обработкой данных. Например, не-
, связанные с обработкой данных. Например, не- связанные с обработкой данных. Например, не- с обработкой данных. Например, не- с обработкой данных. Например, не- обработкой данных. Например, не- обработкой данных. Например, не- данных. Например, не- данных. Например, не-
. Например, не-
Например, не- допустимое преобразование типов, деление на ноль и так далее.
OperationalError
Ошибки, связанные с работой самой базы данных. Напри-
, связанные с работой самой базы данных. Напри- связанные с работой самой базы данных. Напри- с работой самой базы данных. Напри- с работой самой базы данных. Напри- работой самой базы данных. Напри- работой самой базы данных. Напри- самой базы данных. Напри- самой базы данных. Напри- базы данных. Напри- базы данных. Напри- данных. Напри- данных. Напри-
. Напри-
Напри- мер, потеря соединения.

382
Глава 17. Доступ к базам данных
Исключение
Описание
IntegrityError
Ошибки, связанные с нарушением целостности базы дан- ных.
InternalError
Внутренняя ошибка базы данных. Например, обращение к устаревшему курсору.
ProgrammingError
Ошибки в запросах SQL.
NotSupportedError
Ошибки обращения к методам программного интерфейса, которые не поддерживаются базой данных.
Модули могут также объявлять исключение Warning, которое используется модулями доступа к базам данных, чтобы предупредить о таких пробле- мах, как усечение данных при записи в базу данных.
Многопоточность
При разработке многопоточных приложений следует помнить, что моду- ли доступа к базам данных могут поддерживать, а могут не поддерживать возможность работы в многопоточном режиме. Каждый модуль объявляет следующие переменные, позволяющие получить дополнительную инфор- мацию об этом.
threadsafety
Целое число, описывающее степень поддержки модулем работы в многопо- точном режиме. Ниже перечислены возможные значения:
0
Работа в многопоточном режиме не поддерживается. Различные пото- ки не могут совместно использовать какие-либо элементы модуля.
1
Модуль поддерживает работу в многопоточном режиме, но соедине- ния не могут совместно использоваться в разных потоках.
2
Модуль и соединения поддерживают работу в многопоточном режиме, но курсоры не могут совместно использоваться в разных потоках.
3
Модуль, соединения и курсоры поддерживают работу в многопоточ- ном режиме.
Отображение результатов в словари
Часто возникает необходимость отобразить результаты, полученные из базы данных в виде кортежей или списков, в словарь с именованными по- лями. Например, если набор данных, полученный в результате запроса, со- держит большое число столбцов, с ним было бы проще работать, используя описательные имена полей вместо жестко заданных числовых индексов в кортеже.
Решить эту проблему можно множеством способов, но один из самых эле- гантных заключается в использовании функций-генераторов. Например:
(продолжение)

Модуль sqlite3
383
def generate_dicts(cur):
import itertools fieldnames = [d[0].lower() for d in cur.description ]
while True:
rows = cur.fetchmany()
if not row: return for row in rows:
yield dict(itertools.izip(fieldnames,row))
ёё
# Пример использования cur.execute(“select name, shares, price from portfolio”)
for r in generate_dicts(cur):
print r[‘name’],r[‘shares’],r[‘price’]
Имейте в виду, что способ именования столбцов в разных базах данных мо- жет отличаться, особенно это касается чувствительности к регистру симво- лов. Поэтому вам придется быть достаточно внимательными при попытке применить этот прием в программном коде, который должен обеспечивать возможность работы с различными модулями доступа к базам данных.
Расширение интерфейса доступа к базам данных
В заключение следует отметить, что к конкретным модулям баз данных может быть добавлено множество расширений и дополнительных возмож- ностей, например поддержка двухфазного подтверждения транзакций или расширенная обработка ошибок. Дополнительную информацию о реко- мендуемых интерфейсах подобных улучшений можно найти в документе
PEP-249. Кроме того, сторонние модули могут существенно упростить ра-
-249. Кроме того, сторонние модули могут существенно упростить ра- боту с интерфейсами доступа к реляционным базам данных.
Модуль sqlite3
Модуль sqlite3 реализует интерфейс к библиотеке базы данных SQLite
(http://www.sqlite.org). SQLite – это библиотека на языке C, которая реали-
C, которая реали-
, которая реали- зует функциональность реляционной базы данных, размещаемой в едином файле или в области памяти. Несмотря на свою простоту, эта библиотека может оказаться весьма привлекательной по различным причинам. Во- первых, она не требует выделения специального сервера баз данных и не требует сложной настройки – ее можно начинать использовать, просто установив соединение с файлом базы данных (если этот файл отсутствует, будет создан новый). Кроме всего прочего, эта база данных поддерживает транзакции, что повышает ее надежность (даже в случае системных сбоев), а также имеет механизм блокировок, что позволяет одновременно работать с одним и тем же файлом базы данных из нескольких процессов.
Программный интерфейс к библиотеке следует соглашениям, описанным в предыдущем разделе, посвященном интерфейсу доступа к базам данных, поэтому здесь мы не будем повторять описание многих особенностей. Вме- сто этого в данном разделе мы сосредоточимся на технических подробно- стях использования модуля, а также на особенностях, характерных для модуля sqlite3.

384
Глава 17. Доступ к базам данных
Функции уровня модуля
В модуле sqlite3 определены следующие функции:
connect(database [, timeout [, isolation_level [, detect_types]]])
Создает соединение с базой данных SQLite. В аргументе database передается строка, определяющая имя файла базы данных. В нем также можно пере- дать строку “:memory:”; в этом случае база данных будет создана в памяти
(имейте в виду, что база данных этого типа существует, только пока вы- полняется программа на языке Python, и исчезает сразу после завершения программы). Аргумент timeout определяет интервал времени ожидания освобождения внутренней блокировки на доступ для чтения-записи, пока другие соединения выполняют изменения данных в базе. По умолчанию предельное время ожидания составляет 5 секунд. Когда используются та- кие операторы SQL, как INSERT или UPDATE, автоматически запускается но- вая транзакция, если она не была запущена ранее. В аргументе isolation_
level
передается строка с необязательным дополнительным модификато- ром инструкции SQL BEGIN, которая используется для запуска транзакции.
Возможные значения: “” (по умолчанию), “DEFERRED”, “EXCLUSIVE” или “IMME-
DIATE”
. Эти модификаторы имеют отношение к реализации механизма бло-
Эти модификаторы имеют отношение к реализации механизма бло- кировок в базе данных и имеют следующий смысл:
Уровень изоляции
Описание
“”
(пустая строка)
Используется значение по умолчанию – DEFFERED.
“DEFFERED”
Выполняется запуск новой транзакции, но блокировка устанавливается только в момент выполнения первой операции.
“EXCLUSIVE”
Запускает новую транзакцию и гарантирует, что ни- какое другое соединение с базой данных не сможет выполнять операции чтения или записи, пока не будет подтверждена эта транзакция.
“IMMEDIATE”
Запускает новую транзакцию и гарантирует, что ника- кое другое соединение с базой данных не сможет выпол- нять изменения, пока не будет подтверждена эта тран- закция. Однако при этом остальные соединения смогут выполнять операции чтения из базы данных.
Аргумент detect_types позволяет организовать дополнительное определение типов данных (за счет дополнительного синтаксического анализа запросов
SQL) в возвращаемых наборах данных. По умолчанию имеет значение 0
(дополнительное определение не производится). Может устанавливаться как битная маска, составленная из флагов PARSE_DECLTYPES и PARSE_COLNAMES с помощью битовой операции ИЛИ. Если установлен флаг PARSE_DECLTYPES, запросы проверяются на наличие в них имен типов, таких как “integer” или “number(8)”, чтобы определить типы столбцов в возвращаемом наборе данных. Если установлен флаг PARSE_COLNAMES, появляется возможность встраивать в запросы специальные строки вида “colname [typename]” (вклю-

Модуль sqlite3
385
чая кавычки), где colname – имя столбца, а typename – имя типа, зарегистри- рованного с помощью функции register_converter(), описываемой ниже.
При передаче механизму SQLite эти строки просто преобразуются в строки
colname
, а дополнительный спецификатор типа используется при преобра- зовании значений, полученных в результате запроса. Например, такой за- прос, как ‘select price as “price [decimal]” from portfolio’, будет интерпре- тироваться как ‘select price as price from portfolio’, а результаты будут преобразованы в соответствии с правилом «decimal».
register_converter(typename, func)
Регистрирует новое имя типа для последующего использования в качестве значения аргумента detect_types функции connect(). В аргументе typename передается строка, содержащая имя типа в том виде, в каком оно будет использоваться в запросах, а в аргументе func – функция, принимающая единственную строку байтов и возвращающая тип данных в языке Python.
Так, если выполнить вызов sqlite3.register_converter(‘decimal’, decimal.Dec-
3.register_converter(‘decimal’, decimal.Dec- register_converter(‘decimal’, decimal.Dec-
_converter(‘decimal’, decimal.Dec- converter(‘decimal’, decimal.Dec-
(‘decimal’, decimal.Dec- decimal’, decimal.Dec-
’, decimal.Dec- decimal.Dec-
.Dec-
Dec- imal)
, появится возможность запрашивать значения, которые будут преоб- разованы в объекты Decimal, например: ‘select price as “price [decimal]” from stocks’
register_adapter(type, func)
Регистрирует функцию преобразования типа type в языке Python, которая будет использоваться при попытке сохранить значение этого типа в базе данных. В аргументе func передается функция, принимающая экземпляр типа type и возвращающая значение типа int, float, строку байтов в коди- ровке UTF-8, строку Юникода или буфер. Например, если потребуется со-
UTF-8, строку Юникода или буфер. Например, если потребуется со-
-8, строку Юникода или буфер. Например, если потребуется со- хранить в базе данных объект типа Decimal, это можно реализовать вызо- вом sqlite3.register_adapter(decimal.Decimal,float).
complete_statement(s)
Возвращает True, если строка s содержит одну или более полных инструк- содержит одну или более полных инструк- одну или более полных инструк- одну или более полных инструк- или более полных инструк- или более полных инструк- более полных инструк- более полных инструк- полных инструк- полных инструк- инструк- инструк- ций на языке SQL, разделенных точкой с запятой. Это может пригодиться при разработке интерактивных программ, которые получают запросы от пользователя.
enable_callback_tracebacks(flag)
Определяет необходимость обработки исключений, возникших в пользо- вательских функциях обратного вызова, таких как функции, зарегистри- рованные с помощью функций register_converter() и register_adapter(). По умолчанию исключения игнорируются. Если в аргументе flag передать значение True, сообщения с трассировочной информацией будут выводить- ся в поток sys.stderr.
Объекты класса Connection
Объект c класса Connection возвращается функцией connect() и поддержи- вает стандартные операции, описанные в разделе, посвященном описанию интерфейса доступа к базам данных. В дополнение к ним предоставляются следующие методы, характерные для модуля sqlite3.

386
Глава 17. Доступ к базам данных
c.create_function(name, num_params, func)
Регистрирует пользовательскую функцию для использования в запросах
SQL. В аргументе name передается строка с именем функции, в аргументе
num_params
– целое число, определяющее количество параметров, и в аргу- менте func – функция на языке Python, содержащая реализацию. Ниже приводится простой пример:
def toupper(s):
return s.upper()
c.create_function(“toupper”,1,toupper)
ёё
# Пример использования в запросе c.execute(“select toupper(name),foo,bar from sometable”)
Даже при том, что функция записывается на языке Python, ее аргумента-
Python, ее аргумента-
, ее аргумента- ми могут быть только значения типов int, float, str, unicode, buffer или None.
c.create_aggregate(name, num_params, aggregate_class)
Регистрирует пользовательскую агрегатную функцию для использования в запросах SQL. В аргументе name передается строка с именем функции, а в аргументе num_params – целое число, определяющее количество вход- ных параметров. В аргументе aggregate_class указывается класс, реали- зующий агрегатную операцию. Этот класс должен поддерживать инициа- лизацию без параметров и реализовать метод step(params), принимающий то же число параметров, которое указано в аргументе num_params, и метод finalize()
, возвращающий окончательный результат. Ниже приводится простой пример:
class Averager(object):
def __init__(self):
self.total = 0.0
self.count = 0
def step(self,value):
self.total += value self.count += 1
def finalize(self):
return self.total / self.count
ёё
c.create_aggregate(“myavg”,1,Averager)
ёё
# Пример использования в запросе c.execute(“select myavg(num) from sometable”)
Агрегатная операция выполняется как последовательность вызовов мето- да step() с входными значениями и последующим вызовом метода final- ize()
для получения окончательного значения.
c.create_collation(name, func)
Регистрирует пользовательскую функцию сравнивания для использова- ния в запросах SQL. В аргументе name передается строка с именем функции сравнивания, а в аргументе func – функция, принимающая два аргумента и возвращающая значение -1, 0 или 1, в зависимости от того, является ли

Модуль sqlite3
387
первый аргумент меньшим, равным или большим второго. Пользователь- ская функция может использоваться в выражениях на языке SQL, таких как “select * from table order by colname collate name”.
c.execute(sql [, params])
Обеспечивает упрощенный способ создания объекта курсора с помощью метода c.cursor() с последующим вызовом метода execute() курсора. В аргу- менте sql передается запрос SQL, а в аргументе params – параметры запроса.
c.executemany(sql [, params])
Обеспечивает упрощенный способ создания объекта курсора с помощью метода c.cursor() с последующим вызовом метода executemany() курсора.
В аргументе sql передается запрос SQL, а в аргументе params – параметры запроса.
c.executescript(sql)
Обеспечивает упрощенный способ создания объекта курсора с помощью метода c.cursor() с последующим вызовом метода executescript() курсора.
В аргументе sql передается запрос SQL.
c.interrupt()
Прерывает выполнение запросов, выполняющихся в данном соединении.
Этот метод предназначен для вызова из другого потока выполнения.
c.iterdump()
Возвращает итератор, который выводит все содержимое базы данных в виде серии инструкций SQL, которые в свою очередь могут использовать-
SQL, которые в свою очередь могут использовать-
, которые в свою очередь могут использовать- ся для воссоздания базы данных. Этот метод может пригодиться для экс- портирования базы данных в другое место или при необходимости сохра- нить в файле базу данных, расположенную в памяти, для последующего восстановления.
c.set_authorizer(auth_callback)
Регистрирует функцию авторизации, которая вызывается при каждой по- пытке обратиться к столбцу данных в базе. Функция должна принимать пять аргументов, в виде: auth_callback(code, arg1, arg2, dbname, innername).
Значение, возвращаемое этой функцией, может быть одним из следую- щих: SQLITE_OK – если доступ разрешен, SQLITE_DENY – если попытка досту- па должна завершаться ошибкой, и SQLITE_IGNORE – если вместо фактиче- ского значения столбца должно возвращаться значение Null. В первом ар- гументе code функции будет передаваться целочисленный код операции.
В аргументах arg1 и arg2 – параметры операции, значения которых зави- сят от кода операции. В аргументе dbname передается строка с именем базы данных (обычно “main”), в аргументе innername – имя внутреннего представ- ления или триггера, осуществляющего попытку доступа, или None, если отсутствует активное представление или триггер. В следующей таблице приводится список значений кодов операций и интерпретация параметров
arg1
и arg2:

388
Глава 17. Доступ к базам данных
Код операции
arg1
arg2
SQLITE_CREATE_INDEX
Имя индекса
Имя таблицы
SQLITE_CREATE_TABLE
Имя таблицы
None
SQLITE_CREATE_TEMP_INDEX
Имя индекса
Имя таблицы
SQLITE_CREATE_TEMP_TABLE
Имя таблицы
None
SQLITE_CREATE_TEMP_TRIGGER
Имя триггера
Имя таблицы
SQLITE_CREATE_TEMP_VIEW
Имя представления
None
SQLITE_CREATE_TRIGGER
Имя триггера
Имя таблицы
SQLITE_CREATE_VIEW
Имя представления
None
SQLITE_DELETE
Имя таблицы
None
SQLITE_DROP_INDEX
Имя индекса
Имя таблицы
SQLITE_DROP_TABLE
Имя таблицы
None
SQLITE_DROP_TEMP_INDEX
Имя индекса
Имя таблицы
SQLITE_DROP_TEMP_TABLE
Имя таблицы
None
SQLITE_DROP_TEMP_TRIGGER
Имя триггера
Имя таблицы
SQLITE_DROP_TEMP_VIEW
Имя представления
None
SQLITE_DROP_TRIGGER
Имя триггера
Имя таблицы
SQLITE_DROP_VIEW
Имя представления
None
SQLITE_INSERT
Имя таблицы
None
SQLITE_PRAGMA
Имя директивы
None
SQLITE_READ
Имя таблицы
Имя столбца
SQLITE_SELECT
None
None
SQLITE_TRANSACTION
None
None
SQLITE_UPDATE
Имя таблицы
Имя столбца
SQLITE_ATTACH
Имя файла
None
SQLITE_DETACH
Имя базы данных
None
SQLITE_ALTER_TABLE
Имя базы данных
Имя таблицы
SQLITE_REINDEX
Имя индекса
None
SQLITE_ANALYZE
Имя таблицы
None
SQLITE_CREATE_VTABLE
Имя таблицы
Имя модуля
SQLITE_DROP_VTABLE
Имя таблицы
Имя модуля
SQLITE_FUNCTION
Имя функции
None

Модуль sqlite3
389
c.set_progress_handler(handler, n)
Регистрирует функцию обратного вызова, которая должна вызываться при выполнении каждой n-й инструкции виртуальной машины SQLite. В аргу-
SQLite. В аргу-
. В аргу- аргу- аргу- менте handler передается функция, не имеющая аргументов.
Ниже приводятся дополнительные атрибуты объектов соединений.
c.row_factory
Функция, которая вызывается для создания объекта, представляющего содержимое записи в возвращаемом наборе данных. Эта функция должна принимать два аргумента: объект курсора, используемый для получения результатов, и кортеж с исходной записью.
c.text_factory
Функция, которая вызывается для создания объекта, представляющего текстовые значения в базе данных. Функция должна принимать един- ственный аргумент – строку байтов в кодировке UTF-8. Возвращаемое зна-
UTF-8. Возвращаемое зна-
-8. Возвращаемое зна- чение должно быть строкой какого-либо типа. По умолчанию возвращает- ся строка Юникода.
c.total_changes
Целое число записей, которые были изменены с момента открытия соеди- нения с базой данных.
Последняя особенность объектов соединений заключается в том, что они могут использоваться совместно с менеджером контекста, обеспечивая ав- томатическую обработку транзакций. Например:
conn = sqlite.connect(“somedb”)
with conn:
conn.execute(“insert into sometable values (?,?)”, (“foo”,”bar”)))
В данном примере после выполнения всех инструкций в блоке with, если не возникло никаких ошибок, автоматически будет вызван метод commit().
Если будет возбуждено какое-либо исключение, будет выполнена операция rollback()
, а исключение будет возбуждено повторно.
Курсоры и основные операции
Прежде чем приступать к выполнению операций в базе данных sqlite3, не- обходимо создать объект курсора, с помощью метода cursor() объекта со- единения. После этого можно будет использовать методы курсора execute(), executemany()
и executescript() для выполнения инструкций SQL. Общее описание этих методов приводится в разделе «Прикладной интерфейс до- ступа к реляционным базам данных». Вместо того чтобы повторять эту ин- формацию здесь, мы рассмотрим примеры типичных случаев их использо- вания вместе с примерами программного кода. Цель этого раздела состоит в том, чтобы показать, как действуют объекты курсоров, и продемонстри- ровать некоторые наиболее типичные запросы SQL – для тех, кому необхо-
SQL – для тех, кому необхо-
– для тех, кому необхо- димо быстро вспомнить их синтаксис.

390
Глава 17. Доступ к базам данных
Создание новых таблиц в базе данных
В следующем примере показано, как открывать базу данных и как созда- вать новые таблицы:
import sqlite3
conn = sqlite3.connect(“mydb”)
cur = conn.cursor()
cur.execute(“create table stocks (symbol text, shares integer, price real)”)
conn.commit()
При определении новых таблиц необходимо использовать элементарные типы данных SQLite: text, integer, real и blob. Тип blob представляет строки байтов, тогда как тип text представляет строки Юникода в кодировке UTF-8.
Добавление новых значений в таблицы
Следующий пример демонстрирует, как выполняется добавление новых записей в таблицу:
import sqlite3
conn = sqlite3.connect(“mydb”)
cur = conn.cursor()
cur.execute(“insert into stocks values (?,?,?)”,(‘IBM’,50,91.10))
cur.execute(“insert into stocks values (?,?,?)”,(‘AAPL’,100,123.45))
conn.commit()
При добавлении новых значений всегда желательно использовать символы подстановки ?, как показано в примере. Каждый символ ? замещается зна- чением из кортежа, который передается в качестве параметра.
Для добавления в таблицу целых последовательностей данных можно ис- пользовать метод курсора executemany(), как показано ниже:
stocks = [ (‘GOOG’,75,380.13),
(‘AA’,60,14.20),
(‘AIG’,125, 0.99) ]
cur.executemany(“insert into stocks values (?,?,?)”,stocks)
Изменение существующих записей
Ниже приводится пример, как можно изменять значения столбцов в суще- ствующих записях:
cur.execute(“update stocks set shares=? where symbol=?”,(50,’IBM’))
Как и при добавлении новых строк, здесь также желательно использовать в инструкциях SQL символы подстановки ? и передавать фактические зна- чения в виде кортежа.
Удаление записей
Следующий пример демонстрирует, как удалять записи:
cur.execute(“delete from stocks where symbol=?”,(‘SCOX’,))

Модули доступа к базам данных типа DBM
391
Выполнение простых запросов
Следующий пример демонстрирует, как можно выполнять простые запро- сы и получать результаты:
# Выбрать все данные из таблицы for row in cur.execute(“select * from stocks”):
инструкции
ёё
# Выбрать только некоторые столбцы for shares, price in cur.execute(“select shares,price from stocks”):
инструкции
ёё
# Выбрать записи, соответствующие условию for row in cur.execute(“select * from stocks where symbol=?”,(‘IBM’,))
инструкции
ёё
# Выбрать записи, соответствующие условию, и отсортировать их for row in cur.execute(“select * from stocks order by shares”):
инструкции
ёё
# Выбрать записи, соответствующие условию,
# и отсортировать их в обратном порядке for row in cur.execute(“select * from stocks order by shares desc”):
инструкции
ёё
# Выполнить соединение таблиц по общему столбцу (symbol)
for row in cur.execute(“””select s.symbol, s.shares, p.price from stocks as s, prices as p using(symbol)”””):
инструкции
Модули доступа к базам данных типа DBM
В состав стандартной библиотеки языка Python входят несколько модулей, обеспечивающих доступ к файлам баз данных типа UNIX DBM. Поддержи-
UNIX DBM. Поддержи-
DBM. Поддержи-
DBM. Поддержи-
. Поддержи- вается несколько стандартных типов таких баз данных. Для чтения стан- дартных файлов баз данных UNIX DBM используется модуль dbm. Модуль gdbm используется для чтения файлов баз данных GNU dbm (http://www.
gnu.org/software/gdbm
). Модуль dbhash используется для чтения файлов баз данных, созданных с помощью библиотеки Berkeley DB (http://www.oracle.
com/database/berkeley-db/index.html
). Модуль dumbdbm, написанный исклю- чительно на языке Python, реализует свою собственную простейшую базу данных типа DBM.
Все эти модули предоставляют объекты, которые реализуют доступ к хра- нимым данным по образу и подобию словарей, основанных на строках. То есть они действуют, как обычные словари Python, с тем ограничением, что все ключи и значения могут быть только строками. Файл базы данных обычно открывается с помощью версии функции open().
open(filename [, flag [, mode]])
Эта функция открывает файл базы данных с именем filename и возвращает объект базы данных. В аргументе flag передается значение ‘r’ – для досту-

392
Глава 17. Доступ к базам данных па к базе данных только для чтения, ‘w’ – для доступа на чтение и на за- пись, ‘c’ – для создания файла базы данных, если он отсутствует, или ‘n’, чтобы принудительно создать новый файл базы данных. В аргументе mode передается целое число, определяющее, какой режим доступа будет уста- новлен при создании нового файла базы данных (в UNIX по умолчанию ис-
UNIX по умолчанию ис- по умолчанию ис- пользуется значение 0666).
Объект, возвращаемый функцией open(), как минимум поддерживает сле- дующие операции над словарями:
Операция
Описание
d[key] = value
Вставляет новое значение value в базу данных
value = d[key]
Извлекает значение из базы данных del
d[key]
Удаляет элемент данных из базы
d.close()
Закрывает базу данных
key in d
Проверяет наличие ключа key в базе данных
d.sync()
Сохраняет все изменения в файле
Каждая конкретная реализация может добавлять свои особенности (за дополнительной информацией о них обращайтесь к справочным руковод- ствам соответствующих модулей).
Одна из проблем, связанных с модулями доступа к базам данных типа
DBM, заключается в том, что не все модули могут быть установлены на раз-
, заключается в том, что не все модули могут быть установлены на раз- ные платформы. Например, модули dbm и gdbm не поддерживают операцион- ную систему Windows. Однако программы на языке Python все-таки могут создавать базы данных типа DBM для своего использования. Для решения этой проблемы в состав Python входит модуль anydbm, который способен от- крывать и создавать файлы базы данных DBM. Этот модуль предоставля-
DBM. Этот модуль предоставля-
. Этот модуль предоставля- ет функцию open(), описанную выше, и гарантирует работоспособность во всех платформах. Это достигается за счет поиска доступных модулей DBM и выбора наиболее мощной библиотеки (обычно выбирается библиотека db- hash
, если она доступна). В крайнем случае используется модуль dumbdbm, который доступен всегда.
Также существует еще один модуль whichdb, который содержит функцию whichdb(
filename)
. Эта функция может использоваться для проверки фай- ла с целью определить тип базы данных DBM, с помощью которой он был создан.
В приложениях, для которых проблема переносимости имеет большое зна- чение, как правило, лучше не полагаться на использование этих низко- уровневых модулей. Например, если базу данных DBM создать в одной опе-
DBM создать в одной опе- создать в одной опе- рационной системе, а затем перенести ее в другую операционную систему, есть вероятность, что программа на языке Python не сможет прочитать его, если в системе не будет установлен соответствующий модуль DBM. Не сле-
DBM. Не сле-
. Не сле- дует также использовать эти модули для организации хранения больших

Модуль shelve
393
объемов данных или в ситуациях, когда несколько программ на языке Py-
Py- thon могут одновременно открывать один и тот же файл базы данных, или когда требуется высокая надежность и поддержка транзакций (в подобных случаях более удачным выбором будет модуль sqlite3).
Модуль shelve
Модуль shelve обеспечивает поддержку возможности сохранения объектов, используя для этого специальный объект «хранилища». Своим поведени- ем этот объект напоминает словарь, за исключением того, что все объекты, которые он содержит, сохраняются в базе данных на основе хеш-таблицы, такой как dbhash, dbm или gdbm. Однако, в отличие от этих модулей, круг со- храняемых объектов не ограничивается строками. Сохранить можно лю- бой объект, который совместим с модулем pickle. Хранилище создается вы- создается вы- создается вы- вы- вы- зовом функции shelve.open().
open(filename [,flag=’c’ [, protocol [, writeback]]])
Открывает файл хранилища. Создает новый файл, если он не существует.
В аргументе filename передается имя файла базы данных без расширения.
Аргумент flag имеет тот же смысл, как описанный в начале раздела «Мо- дули доступа к базам данных типа DBM», и может иметь одно из значений:
‘r’
, ‘w’, ‘c’ или ‘n’. Аргумент protocol определяет, какой протокол будет ис- пользоваться для сериализации объектов, сохраняемых в базе данных. Он имеет то же назначение, что и в модуле pickle. Аргумент writeback опреде- ляет политику кэширования объекта базы данных. Если он имеет значе- ние True, все элементы, к которым выполнялось обращение, кэшируются в памяти и сохраняются в файле только в момент закрытия хранилища. По умолчанию используется значение False. Возвращает объект хранилища.
После открытия хранилища над ним могут выполняться следующие опе- рации:
Операция
Описание
d[key] = data
Сохраняет данные с ключом key.
Затирает существующие данные.
data = d[key]
Извлекает данные с ключом key.
del
d[key]
Удаляет данные с ключом key.
d.has_key(key)
Проверяет наличие ключа key в хранилище.
d.keys()
Возвращает все ключи.
d.close()
Закрывает хранилище.
d.sync()
Сохраняет все изменения на диске.
В качестве ключей в хранилище могут использоваться только строки. Объ- екты, сохраняемые в хранилище, должны поддерживать возможность се- риализации с помощью модуля pickle.

394
Глава 17. Доступ к базам данных
Shelf(dict [, protocol [, writeback]])
Класс-примесь, который реализует функциональность хранилища поверх объекта словаря dict. Когда объекты сохраняются в возвращаемом объекте хранилища, они сериализуются и запоминаются в словаре dict. Аргумен- ты protocol и writeback имеют тот же смысл, что и в функции shelve.open().
Модуль shelve использует модуль anydbm для выбора соответствующего мо- дуля DBM. В большинстве стандартных конфигураций Python чаще всего выбирается модуль dbhash, который основан на использовании библиотеки
Berkeley DB.

1   ...   26   27   28   29   30   31   32   33   ...   82


написать администратору сайта