Чтение онлайн

ЖАНРЫ

Язык программирования Python
Шрифт:

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

Листинг

weekdays = [«Воскресенье», «Понедельник», «Вторник», «Среда»,

«Четверг», «Пятница», «Суббота», «Воскресенье»]

import sqlite as db

c = db.connect(database=«tvprogram»)

cu = c.cursor

cu.execute(""«DELETE FROM wd;""")

cu.executemany(""«INSERT INTO wd VALUES (%s, %s);""",

enumerate(weekdays))

c.commit

c.close

Стоит напомнить, что встроенная

функция enumerate создает список пар номер–значение, например:

Листинг

>>> print [i for i in enumerate(['a', 'b', 'c'])]

[(0, 'a'), (1, 'b'), (2, 'c')]

Из приведенного примера ясно, что метод executemany объекта–курсора использует второй параметр — последовательность — для массового ввода данных с помощью SQL–инструкции INSERT.

Предположим, что телепрограмма задана в файле tv.csv в формате CSV (он уже обсуждался):

Листинг

10.02.2003 9.00|ОРТ|Новости|Новости|9.15

10.02.2003 9.15|ОРТ|«НЕЖНЫЙ ЯД»|Сериал|10.15

10.02.2003 10.15|ОРТ|«Маски–шоу»|Юмористическая программа|10.45

10.02.2003 10.45|ОРТ|«Человек и закон»||11.30

10.02.2003 11.30|ОРТ|«НОВЫЕ ПРИКЛЮЧЕНИЯ СИНДБАДА»|Сериал|12.00

Следующая программа разбирает CSV–файл и записывает данные в таблицу tv:

Листинг

import calendar, csv

import sqlite as db

from sqlite.main import Time, Date ## Только для

db.Date, db.Time = Date, Time ## sqlite

c = db.connect(database=«tvprogram»)

cu = c.cursor

input_file = open(«tv.csv», «rb»)

rdr = csv.DictReader(input_file,

fieldnames=['begt', 'channel', 'prname', 'prgenre', 'endt'])

for rec in rdr:

bd, bt = rec['begt'].split

bdd, bdm, bdy = map(int, bd.split('.'))

bth, btm = map(int, bt.split('.'))

eth, etm = map(int, rec['endt'].split('.'))

rec['wd'] = calendar.weekday(bdy, bdm, bdd)

rec['begd'] = db.Date(bdy, bdm, bdd)

rec['begt'] = db.Time(bth, btm, 0)

rec['endt'] = db.Time(eth, etm, 0)

cu.execute(""«INSERT INTO tv

(tvdate, tvweekday, tvchannel, tvtime1, tvtime2, prname, prgenre)

VALUES (

%(begd)s, %(wd)s, %(channel)s, %(begt)s, %(endt)s,

%(prname)s, %(prgenre)s);""", rec)

input_file.close

c.commit

Большая часть преобразований связана с получением дат и времен (приходится разбивать строки на части в соответствии с форматом даты и времени). День недели получен с помощью функции из модуля calendar.

Примечание:

Из–за небольшой ошибки в пакете sqlite конструкторы Date, Time и т.д. не попадают из модуля sqlite.main при импорте из sqlite, поэтому пришлось добавить две строки, специфичные для sqlite, в универсальный «модуль» с именем db.

В этом же примере было продемонстрировано использование словаря для вставки значений в таблицу базы данных. Следует заметить, что подстановка выполняется внутри вызова execute в соответствии с типами переданных значений. SQL–инструкция INSERT была бы некорректной при попытке выполнить подстановку самостоятельно, например, операцией форматирования %.

Выборки из базы данных

Базы

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

Листинг

import sqlite as db

c = db.connect(database=«tvprogram»)

cu = c.cursor

cu.execute(«SELECT weekday, wdname FROM wd ORDER BY weekday;")

for i, n in cu.fetchall:

print i, n

Если все было сделано правильно, получится:

Листинг

0 Воскресенье

1 Понедельник

2 Вторник

3 Среда

4 Четверг

5 Пятница

6 Суббота

7 Воскресенье

Несложно догадаться, как сделать выборку телепрограммы:

Листинг

import sqlite as db

c = db.connect(database=«tvprogram»)

cu = c.cursor

cu.execute("""

SELECT tvdate, tvtime1, wd.wdname, tvchannel, prname, prgenre

FROM tv, wd

WHERE wd.weekday = tvweekday

ORDER BY tvdate, tvtime1;""")

for rec in cu.fetchall:

dt = rec[0] + rec[1]

weekday = rec[2]

channel = rec[3]

name = rec[4]

genre = rec[5]

print "%s, %02i.%02i.%04i %s %02i:%02i %s (%s)» % (

weekday, dt.day, dt.month, dt.year, channel,

dt.hour, dt.minute, name, genre)

В этом примере в качестве типа для даты и времени используется тип из mx.DateTime. Именно поэтому стало возможным получить год, месяц, день, час и минуту обращением к атрибуту. Кстати, datetime–объект стандартного модуля datetime имеет те же атрибуты. В общем случае для даты и времени может использоваться другой тип, поэтому если получаемые из базы даты будут проходить более глубокую обработку, их следует переводить во внутреннее представление сразу после получения по запросу. Тем самым тип даты из модуля DB–API не будет влиять на другие части программы.

Другие СУБД и Python

Модуль sqlite дает прекрасные возможности для построения небольших и быстрых баз данных, однако для полноты изложения предлагается обзор модулей расширения Python для других СУБД.

Выше везде импортировался модуль sqlite, с изменением его имени на db. Это было сделано не случайно. Дело в том, что подобные модули, поддерживающие DB–API 2.0, есть и для других СУБД, и даже не в единственном числе. Согласно информации на сайте www.python.org DB–API 2.0–совместимые модули для Python имеют следующие СУБД или протоколы доступа к БД:

zxJDBC Доступ по JDBC.

MySQL Для СУБД MySQL.

mxODBC Доступ по ODBC, продается фирмой eGenix .

DCOracle2, cx_Oracle Для СУБД Oracle.

PyGresQL, psycopg, pyPgSQL Для СУБД PostgreSQL.

Sybase Для Sybase.

sapdbapi Для СУБД SAP.

KInterbasDB Для СУБД Firebird (это потомок Interbase).

PyADO Адаптер к Microsoft ActiveX Data Objects (только под Windows).

Примечание:

Для СУБД PostgreSQL нужно взять не PyGreSQL, а psycopg, так как в первом есть небольшие проблемы с типом для даты и времени при вставке параметров в методе execute. Кроме того, psycopg оптимизирован для скорости и многопоточности (psycopg.threadsafety=2).

Поделиться с друзьями: