su13@pochta.ru

| Первый | Второй | Третий | Четвёртый | Пятый | Шестой | Седьмой |


Глава №11.

Python

Если вы пишете много программ на Perl, но не знакомы с Python, вам определенно следует познакомиться с ним. Python является объектно-ориентированным языком сценариев, сочетающим мощь таких языков, как Perl и Tсl, с понятным синтаксисом, что позволяет создавать приложения, которые легко поддерживать и развивать. Отличное введение в программирование на Python дается в книге Марка Лутца (Mark Lutz) и Дэвида Эшера (David Asher) «Learning Python», изданной O'Reilly & Associates, Inc. В данной главе предполагается наличие у читателя знакомства с основами языка Python, включая умение добавлять новые модули к начальной инсталляции Python.

Поддержка баз данных MySQL и mSQL со стороны Python, которая является предметом данной главы, осуществляется посредством двух модулей Python. В момент публикации данной книги модуль для mSQL был доступен на http://www.python.org, а для MySQL - на http://www.mysql.com. Хотя есть несколько других модулей, обеспечивающих приложениям Python доступ к MySQL и mSQL, они, как и эти два, являются, в основном, вариациями на тему С API для MySQL и mSQL. Для доступа к выбранной вами базе данных и выполнения примеров этой главы необходимо установить один или оба этих модуля.

Оба API практически одинаковы, поэтому мы будем рассказывать сразу об обоих, оговаривая.места, где между ними есть различия.

Основы подключения к базам данных

API для Python являются, вероятно, самыми простыми API для работы с базами данных из всех, встречающихся в этой книге. Как и для других API, начать нужно с подключения к базам данных — установления соединения. Поскольку Python имеет интерактивный интерфейс, продемонстрировать соединение проще всего с помощью интерпретатора командной строки. Ниже показаны две сессии Python, демонстрирующие простое соединение с базами данных MySQL и mSQL соответственно. В первом примере производится соединение с базой данных MySQL:

[4:30pm] athens> python

Python 1.5.1 (#1, Jun 13 1998, 22:38:15) [GCC 2.7.2] on sunos5

Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam

>>> import MySQL;

>>> db = MySQL.connect( 'athens. imaginary.com');

>>> db.selectdb('db_test');

>>> result = db.do('select test_val from test where test_id = 1');

>>> print result;

[['This is a MySQL test.']]

>>>

Код для mSQL, делающий то же самое, выглядит почти идентично:

[4:30pm] athens> python

Python 1.5.1 (#1, Jun 13 1998, 22:38:15) [GCC 2.7.2] on sunos5

Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam

>>> import mSQL;

>>> db = mSQL.connect('athens. imaginary.com');

>>> db.selectdb('db_test');

>>> result = db.query('select test_val from test where test_id = 1');

>>> print result;

[('This is a mSQL test.',)]

>>>

В обоих случаях прежде всего нужно импортировать соответствующий модуль Python. He следует использовать синтаксис mSQL import *, так как он засорит пространство имен вашего приложения. Вместо этого в каждом модуле следует получить экземпляр описателя базы данных с помощью метода connect() и использовать этот описатель для доступа к базе данных.

Вызов connect() в обоих API схож, но не одинаков. В приведенном примере подключения к MySQL мы подключаемся к базе данных, для которой разрешен глобальный доступ. Поскольку в этом случае не требуется указания имени пользователя или пароля, вызов connect() для сессии MySQL выглядит так же, как для сессии mSQL. Однако вы можете задать имя пользователя и пароль, если того требует ваша база данных MySQL. Например, db = MySQL.connect( 'athens. imaginary.com', 'myuid', 'password'); подключит вас к серверу MySQL на athens.imagi-nary.com в качестве «myuid» с паролем «password». Тот и другой API не требуют имени узла при локальном подключении. В этом случае они достаточно сообразительны и для более быстрого соединения используют сокет домена Unix (на Unix-системах).

Процесс соединения в С API является двухэтапным и требует сначала соединиться с сервером, а затем выбрать базу данных, которую вы хотите использовать. Для API Python требуются те же шаги. Как для MySQL, так и для mSQL метод API для выбора базы данных практически одинаков: selectdb() . В большинстве случаев вы передаете этому методу единственный параметр - имя базы данных. MySQL поддерживает необязательный второй параметр, позволяющий потребовать, чтобы результирующий набор оставался на сервере, пока не будет запрошена каждая его строка. Этот вариант требуется только тогда, когда вы знаете, что память клиента ограниченна, или извлекаете очень большой результирующий набор.

Запросы

Эти два API слегка различаются в том способе, каким посылаются команды базе данных и обрабатываются возвращаемые результаты. API для mSQL очень прост и не имеет поддержки курсоров. Напротив, API для MySQL поддерживает простой mSQL API, а также более сложный набор методов API, которые более точно отражают С API и обеспечивают поддержку курсоров. При программировании на Python поддержка курсоров имеет сомнительную ценность, поскольку ни одна из этих баз данных не поддерживает редактирование по месту, а упрощенный API, показанный в интерактивных сессиях, позволяет перемещаться вперед и назад по результирующему набору с такой же легкостью, как и с помощью курсора. Однако далее в этой главе мы найдем применение для курсора, поскольку метод API, обеспечивающий поддержку курсора, обеспечивает также поддержку динамического доступа к базе данных.

mSQL API и простая форма MySQL API позволяют приложению запрашивать базу данных и выводить результаты в виде списка. К несчастью, эти API имеют тривиальное, но неприятное различие в том, каким образом это делается. Во-первых, для mSQL метод запроса называется query(), а для MySQL он называется do(). Каждый из методов воспринимает в качестве аргумента любую строку SQL. Если команда порождает результирующий набор, он возвращается в виде списка: списка кортежей для mSQL и списка списков для MySQL.

В большинстве случаев различие в типе возвращаемых значений несущественно: кортежи не могут изменяться. Код в большинстве случаев одинаков. Тем не менее следует помнить, что строки MySQL являются списками, а строки mSQL - кортежами, на случай, если вы столкнетесь с ситуацией, где это различие существенно. В примере 11-1 приводится простая Python-программа, обращающаяся к базам данных MySQL и mSQL и выводящая результаты.

Пример 11-1. Обработка запросов в Python дд,я mSQL и MySQL

#!\/usr/local/bin/python

# Импорт модулей import Msql, MySQL;

# Инициализация значений database и query

database = 'db_test';

query = 'SELECT test_id, test_val FROM test';

# Соединение с серверами msql = mSQL.connect();

mysql = MySQL.connect();

# Выбор тестовых баз данных msql.selectdb(database);

mysql.selectdb(database);

# Выполнение запроса

m_result = msql.query(query);

my_result = mysql.do(query);

#Обработка результатов для mSQL

for row in m_result:

# Здесь row является кортежем

print "mSQL- test_id: ",row[0]," test_val: ",row[1];

# Обработка результатов для MySQL

for row in my_result:

ft Здесь row является списком

print "MySQL- test_id: ",row[0]," | test_val: ",row[1];

# Закрыть соединение (только mSQL)

msql.close();

Для обеих баз данных, MySQL и mSQL, приложение просматривает в цикле каждую строку результирующего набора и выводит ее данные. В mSQL первый элемент кортежа представляет первую колонку запроса, а второй элемент - вторую колонку. Аналогично, первый элемент в списке MySQL представляет первую колонку запроса, а второй элемент - вторую колонку.

Обновление

Обновление, вставка и удаление в базе данных производится с помощью того же метода API, что и запросы, - просто не требуется обрабатывать результирующий набор. Иными словами, вызовите query() или do(), и больше ничего не требуется. В MySQL есть дополнительная возможность возврата значения AUTO_INCREMENT , если в затронутой таблице есть поле с атрибутом AUTO_INCREMENT .

Динамическое соединение с базами данных

Тот метод API, который мы до сих пор обсуждали в этой главе, дает, в сущности, все необходимое для простых и наиболее часто встречающихся повседневных задач выборки, вставки, обновления и удаления данных в базе. В некоторых более сложных приложениях может оказаться, что вы ничего (или чего-нибудь) не знаете о базе данных, с которой соединяетесь и которой посылаете команды. Хотя оба API поддерживают метаданные уровня базы данных - информацию времени выполнения о базе данных, с которой соединены, - только MySQL API обеспечивает полную поддержку динамически генерируемых вызовов SQL, включая метаданные результирующего набора.

Описатели команд в MySQL

Как уже отмечалось, в MySQL есть два средства обработки запросов. Более простая форма возвращает результирующий набор в виде списка списков. Более сложная форма возвращает описатель команды.

Описатель команды представляет результаты обработки запроса к MySQL через метод query() (в противоположность использованию метода do()). Пример 11-2 показывает, как можно использовать описатель команды для получения информации времени выполнения о запросе или команде обновления.

Пример 11-2. Динамический доступ к базе данных MySQL с помощью описателя команды

[7:20pm] athens> python

Python 1.5.1 (#1, Jun 13 1998, 22:38:15) [GCC 2.7.2] on- sunos5

Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam

>>> import MySQL;

>>> db = MySQL,con.nect();

>>> db.selectdb('db_test-);

>>> result - db.query("INSERT INTO test(test_id,test_val) VALUES(4,

'Bing!')");

>>> print result.affectedrows();

1

>>> result = db.query("SELECT * FROM test");

>>> print result. numrows();

3

>>> print result.fields();

[['test_id', 'test', 'long', 11, 'notnull'], ['test_val', 'test', 'string',

100, "]]

>>> print result, fetchrows(-l);

[[1, 'This is a test.'], [2, 'This is a test.'], [4. 'Bing!']]

>>>

В дополнение к результирующему набору запроса можно с помощью описателя команды получить число строк, затронутых операциями обновления, вставки или удаления. В примере 11-2 мы получили количество строк, возвращенных запросом, и подробные сведения о колонках, представленных в результирующем наборе.

Из новых методов, появившихся в примере 11-2, только fetchrows() не является самоочевидным. Этот метод получает очередную группу строк в количестве, определяемом переданным ему параметром. Иными словами, при вызове result. fetchrows(2) возвращается список, состоящий из очередных двух строк. Метод возвращает список, состоящий из всех строк, если ему передан параметр, меньший 0 — как в данном примере. Сочетая этот метод с обращением к seek(), можно перемещаться по результирующему набору. Метод seek() принимает целочисленный параметр, указывающий на строку, с которой вы хотите работать, при этом 0 указывает на первую строку.

Метаданные базы данных

Хотя только MySQL API поддерживает динамическое управление результирующим набором (по крайней мере, на момент данной публикации), оба API поддерживают метаданные базы данных с помощью почти идентичных наборов методов. Метаданные базы данных представляют собой информацию о соединении с базой данных. В примере 11-3 приведена сессия Python, заставляющая соединения с MySQL и mSQL рассказать о себе.

Пример 11-3. Данные

[7:56pm] athens> python

Python 1.5.1 (#1, Jun 13 1998, 22:38:15) [GCC 2.7.2] on sunos5

Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam

>>> import mSQL, MySQL;

>>> msql = mSQL.connect();

>>> mysql = MySQL.connect();

>>> print msql.listdbs();

['db_test', 'db_web']

>>> print mysql.listdbs();

[['dbjest'], ['mysql'], ['test']]

>>> msql.selectdb('db_test');

>>> mysql.selectdb('db_test');

>>> print msql. listtables();

['test', 'hosts']

>>> print mysql.listtables();

[['test']]

>>> print msql.serverinfo;

2.0.1

>>> print mysql.serverinfo();

3.21.17a-beta-log

>>> print mysql.clientinfo();

MySQL-Python-1.1

>>> print msql.hostname;

None

>>> print mysql.hostinfo();

Localhost via UNIX socket

>>> print mysql.stat();

Uptime: 4868410 Running threads: 1 Questions: 174 Reloads: 4 Open tables: 4

>>> print mysql.listprocesses();

None

>>>

В этом примере долгая серия обращений к методам обеспечивает вывод расширенной информации о соединениях с базами данных. В ряде случаев mSQL предоставляет эту информацию через неизменяемые атрибуты, а не методы. MySQL API предоставляет значительно больше сведений, чем mSQL. Обратитесь к справочному разделу части III «Справочник» за полным описанием этих методов и атрибутов.

Оглавление

GNU OCXE GNU LINUX
Hosted by uCoz