RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

Глава 5. Примеры Connector/Python

Эти примеры иллюстрируют, как разработать приложения Python и скрипты, которые соединяются с использованием MySQL Connector/Python.

5.1. Соединение с MySQL, используя Connector/Python

Конструктор connect() создает связь с сервером MySQL и возвращает объект MySQLConnection.

Следующий пример показывает, как соединиться с сервером MySQL:

import mysql.connector
cnx = mysql.connector.connect(user='scott', password='password',
                              host='127.0.0.1',
                              database='employees')
cnx.close()

Раздел 7.1 описывает разрешенные аргументы соединения.

Также возможно создать объекты связи, используя класс connection.MySQLConnection():

from mysql.connector import (connection)

cnx = connection.MySQLConnection(user='scott', password='password',
                                 host='127.0.0.1',
                                 database='employees')
cnx.close()

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

Чтобы обработать ошибки связи, используйте try и ловите все ошибки при использовании исключения errors.Error :

import mysql.connector
from mysql.connector import errorcode

try:
cnx = mysql.connector.connect(user='scott', database='employ')
except mysql.connector.Error as err:
  if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
     print("Something is wrong with your user name or password")
  elif err.errno == errorcode.ER_BAD_DB_ERROR:
       print("Database does not exist")
    else:
      print(err)
  else:
    cnx.close()

Определение аргументов соединения в словаре и использование оператора **:

import mysql.connector
config = {
  'user': 'scott',
  'password': 'password',
  'host': '127.0.0.1',
  'database': 'employees',
  'raise_on_warnings': True
}
cnx = mysql.connector.connect(**config)
cnx.close()

Connector/Python Python или расширение C

Connector/Python предлагает два внедрения: чистый интерфейс Python и расширение C, которое пользуется библиотекой клиента (см. главу 8). Это может формироваться во время выполнения, используя параметр use_pure. Это по умолчанию False с MySQL 8 означая, что расширение C используется. Если расширение C недоступно на системе, тогда use_pure по умолчанию True. Установка use_pure=False заставляет связь использовать расширение C, если ваша установка Connector/Python включает его, в то время как use_pure=True означает, что внедрение Python используется при наличии.

Опция use_pure и расширение C были добавлены в Connector/Python 2.1.1.

Следующий пример показывает, как установить use_pure = False.

import mysql.connector
cnx = mysql.connector.connect(user='scott', password='password',
                              host='127.0.0.1',
                              database='employees',
                              use_pure=False)
cnx.close()

Также возможно использовать расширение C непосредственно, импортируя модуль _mysql_connector вместо mysql.connector. Для получения дополнительной информации посмотрите раздел 8.2.

5.2. Создание таблиц используя Connector/Python

Все запросы DDL (Data Definition Language) выполняются, используя структуру, известную как курсор. Следующие примеры показывают, как составить таблицы Employee Sample Database. Вам они нужны для других примеров.

В сервере MySQL таблицы очень долговечные объекты и часто нужен доступ многочисленным запросам, написанным на различных языках. Вы могли бы, как правило, работать с таблицами, которые уже есть, вместо того, чтобы создать их в рамках вашего собственного приложения. Не стои создавать и удалять таблицы много раз, поскольку это дорогая операция. Исключение: temporary tables, которые могут быть составлены и удалены быстро.

from __future__ import print_function
import mysql.connector
from mysql.connector import errorcode

DB_NAME = 'employees'
TABLES = {}
TABLES['employees'] = (
  "CREATE TABLE `employees` ("
    "`emp_no` int(11) NOT NULL AUTO_INCREMENT,"
    "`birth_date` date NOT NULL,"
    "`first_name` varchar(14) NOT NULL,"
    "`last_name` varchar(16) NOT NULL,"
    "`gender` enum('M','F') NOT NULL,"
    "`hire_date` date NOT NULL,"
    "PRIMARY KEY (`emp_no`)"
    ") ENGINE=InnoDB")

TABLES['departments'] = (
  "CREATE TABLE `departments` ("
    "`dept_no` char(4) NOT NULL,"
    "`dept_name` varchar(40) NOT NULL,"
    "PRIMARY KEY (`dept_no`), UNIQUE KEY `dept_name` (`dept_name`)"
    ") ENGINE=InnoDB")

TABLES['salaries'] = (
  "CREATE TABLE `salaries` ("
    "`emp_no` int(11) NOT NULL,"
    "`salary` int(11) NOT NULL,"
    "`from_date` date NOT NULL,"
    "`to_date` date NOT NULL,"
    "PRIMARY KEY (`emp_no`,`from_date`), KEY `emp_no` (`emp_no`),"
    "CONSTRAINT `salaries_ibfk_1` FOREIGN KEY (`emp_no`) "
    " REFERENCES `employees` (`emp_no`) ON DELETE CASCADE"
    ") ENGINE=InnoDB")

TABLES['dept_emp'] = (
  "CREATE TABLE `dept_emp` ("
    "`emp_no` int(11) NOT NULL,"
    "`dept_no` char(4) NOT NULL,"
    "`from_date` date NOT NULL,"
    "`to_date` date NOT NULL,"
    "PRIMARY KEY (`emp_no`,`dept_no`), KEY `emp_no` (`emp_no`),"
    "KEY `dept_no` (`dept_no`),"
    "CONSTRAINT `dept_emp_ibfk_1` FOREIGN KEY (`emp_no`) "
    " REFERENCES `employees` (`emp_no`) ON DELETE CASCADE,"
    "CONSTRAINT `dept_emp_ibfk_2` FOREIGN KEY (`dept_no`) "
    " REFERENCES `departments` (`dept_no`) ON DELETE CASCADE"
    ") ENGINE=InnoDB")

TABLES['dept_manager'] = (
  "CREATE TABLE `dept_manager` ("
    "`dept_no` char(4) NOT NULL,"
    "`emp_no` int(11) NOT NULL,"
    "`from_date` date NOT NULL,"
    "`to_date` date NOT NULL,"
    "PRIMARY KEY (`emp_no`,`dept_no`),"
    "KEY `emp_no` (`emp_no`),"
    "KEY `dept_no` (`dept_no`),"
    "CONSTRAINT `dept_manager_ibfk_1` FOREIGN KEY (`emp_no`) "
    " REFERENCES `employees` (`emp_no`) ON DELETE CASCADE,"
    "CONSTRAINT `dept_manager_ibfk_2` FOREIGN KEY (`dept_no`) "
    " REFERENCES `departments` (`dept_no`) ON DELETE CASCADE"
    ") ENGINE=InnoDB")

TABLES['titles'] = (
  "CREATE TABLE `titles` ("
    "`emp_no` int(11) NOT NULL,"
    "`title` varchar(50) NOT NULL,"
    "`from_date` date NOT NULL,"
    "`to_date` date DEFAULT NULL,"
    "PRIMARY KEY (`emp_no`,`title`,`from_date`), KEY `emp_no` (`emp_no`),"
    "CONSTRAINT `titles_ibfk_1` FOREIGN KEY (`emp_no`)"
    " REFERENCES `employees` (`emp_no`) ON DELETE CASCADE"
    ") ENGINE=InnoDB")

Предыдущий код показывает, как мы храним запросы CREATE в словаре Python TABLES. Мы также определяем базу данных в глобальной переменной DB_NAME, которая позволяет вам легко использовать различную схему.

cnx = mysql.connector.connect(user='scott')
cursor = cnx.cursor()

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

def create_database(cursor):
try:
  cursor.execute(
    "CREATE DATABASE {} DEFAULT CHARACTER SET 'utf8'".format(DB_NAME))
  except mysql.connector.Error as err:
    print("Failed creating database: {}".format(err))
exit(1)

try:
  cursor.execute("USE {}".format(DB_NAME))
  except mysql.connector.Error as err:
    print("Database {} does not exists.".format(DB_NAME))
  if err.errno == errorcode.ER_BAD_DB_ERROR:
     create_database(cursor)
     print("Database {} created successfully.".format(DB_NAME))
     cnx.database = DB_NAME
  else:
    print(err)
exit(1)

Мы сначала пытаемся перейти на конкретную базу данных, используя свойство database объекта связи cnx. Если есть ошибка, мы исследуем код ошибки, чтобы проверить, не существует ли база данных. Если это так, мы вызываем функцию create_database, чтобы создать базу.

На любой другой ошибке приложение выходит и показывает сообщение об ошибке.

После того, как мы успешно создадим или переключимся на целевую базу данных, мы составляем таблицы, повторяя по пунктам словарь TABLES:

for table_name in TABLES:
  table_description = TABLES[table_name]
  try:
    print("Creating table {}: ".format(table_name), end='')
  cursor.execute(table_description)
  except mysql.connector.Error as err:
    if err.errno == errorcode.ER_TABLE_EXISTS_ERROR:
       print("already exists.")
    else:
      print(err.msg)
  else:
    print("OK")
cursor.close()
cnx.close()

Чтобы обработать ошибку, когда таблица уже существует, мы уведомляем пользователя, что это уже было там. Другие ошибки печатаются, но мы продолжаем составлять таблицы. Пример показывает, как обращаться с условием "табьлица уже есть" в целях иллюстрации. В реальном применении мы, как правило, избегали бы состояния ошибки полностью при помощи IF NOT EXISTS в запросе CREATE TABLE.

Вывод был бы чем-то вроде этого:

Database employees does not exists.
Database employees created successfully.
Creating table employees: OK
Creating table departments: already exists.
Creating table salaries: already exists.
Creating table dept_emp: OK
Creating table dept_manager: OK
Creating table titles: OK

Чтобы наполнить таблицы, используйте файлы дампа Employee Sample Database. Обратите внимание на то, что вам нужны только файлы дампа данных, которые вы найдете в архиве employees_db-dump-files-1.0.5.tar.bz2. После загрузки файлов выполните следующие команды, добавив опции связи к командам mysql, если надо:

shell> tar xzf employees_db-dump-files-1.0.5.tar.bz2
shell> cd employees_db
shell> mysql employees < load_employees.dump
shell> mysql employees < load_titles.dump
shell> mysql employees < load_departments.dump
shell> mysql employees < load_salaries.dump
shell> mysql employees < load_dept_emp.dump
shell> mysql employees < load_dept_manager.dump

5.3. Вставка данных используя Connector/Python

Вставка или обновление данных также сделаны, используя структуру, известную как курсор. Когда вы используете механизм системы хранения транзакций, такой как InnoDB (умолчание для MySQL 5.5 и выше), необходимо commit данные после последовательности INSERT, DELETE и UPDATE.

Этот пример показывает, как вставить новые данные. Второй INSERT зависит от значения недавно созданного primary key первого. Пример также демонстрирует, как использовать расширенные форматы. Задача состоит в том, чтобы добавить нового сотрудника, начинающего работать завтра с зарплатой в 50000.

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

from __future__ import print_function
from datetime import date, datetime, timedelta
import mysql.connector

cnx = mysql.connector.connect(user='scott', database='employees')
cursor = cnx.cursor()
tomorrow = datetime.now().date() + timedelta(days=1)

add_employee = ("INSERT INTO employees "
  "(first_name, last_name, hire_date, gender, birth_date) "
  "VALUES (%s, %s, %s, %s, %s)")
add_salary = ("INSERT INTO salaries "
  "(emp_no, salary, from_date, to_date) "
  "VALUES (%(emp_no)s, %(salary)s, %(from_date)s, %(to_date)s)")
data_employee = ('Geert', 'Vanderkelen', tomorrow, 'M', date(1977, 6, 14))

# Insert new employee
cursor.execute(add_employee, data_employee)
emp_no = cursor.lastrowid

# Insert salary information
data_salary = {
  'emp_no': emp_no,
  'salary': 50000,
  'from_date': tomorrow,
  'to_date': date(9999, 1, 1),
}
cursor.execute(add_salary, data_salary)

# Make sure data is committed to the database
cnx.commit()
cursor.close()
cnx.close()

Мы сначала открываем связь с сервером MySQL и сохраняем объект соединения в переменной cnx. Мы тогда создаем новый курсор, по умолчанию это объект MySQLCursor, используя метод связм cursor().

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

Оба запроса INSERT сохранены в переменных add_employee и add_salary. Отметьте что второй INSERT использует расширенные коды формата Python.

Информация нового сотрудника хранится в кортеже data_employee. Запрос, чтобы ввести нового сотрудника выполняется, и мы получаем недавно вставленное значение для столбца emp_no (столбец AUTO_INCREMENT) с использованием свойства lastrowid объекта курсора.

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

Connector/Python по умолчанию выключает autocommit, а MySQL 5.5 и выше используют транзакционные таблицы InnoDB. Поэтому необходимо явно передать ваши изменения, используя метод commit(). Вы могли бы также отменить их методом rollback() .

5.4. Запрос данных, используя Connector/Python

Следующий пример показывает, как запрос данных использует курсор, созданный с использованием метода cursor(). Возвращенные данные отформатированы и выведены на консоль.

Задача состоит в том, чтобы выбрать всех сотрудников, нанятых в 1999 году, и напечатать их имена и даты на консоль.

import datetime
import mysql.connector

cnx = mysql.connector.connect(user='scott', database='employees')
cursor = cnx.cursor()
query = ("SELECT first_name, last_name, hire_date FROM employees "
         "WHERE hire_date BETWEEN %s AND %s")

hire_start = datetime.date(1999, 1, 1)
hire_end = datetime.date(1999, 12, 31)
cursor.execute(query, (hire_start, hire_end))
for (first_name, last_name, hire_date) in cursor:
  print("{}, {} was hired on {:%d %b %Y}".format(
        last_name, first_name, hire_date))
cursor.close()
cnx.close()

Мы сначала открываем связь с сервером MySQL и сохраняем объект соединения в переменную cnx. Затем создаем новый курсор, по умолчанию это объект MySQLCursor, используя метод cursor().

В предыдущем примере мы храним запрос SELECT в переменной query. Обратите внимание на то, что мы используем %s-маркеры без кавычек там, где даты должны были быть. Connector/Python конвертирует hire_start и hire_end из типов Python до типа данных, который MySQL понимает и добавляет необходимые кавычки. В этом случае это заменяет первый %s на '1999-01-01', а второй на '1999-12-31'.

Мы тогда выполняем операцию, сохраненную в переменной query, используя метод execute(). Данные, раньше заменившие %s-маркеры в запросе, передаются как кортеж: (hire_start, hire_end).

После выполнения запроса сервер MySQL готов послать данные. Набор результатов может быть пустым, одной строкой или 100 миллионами строк. В зависимости от ожидаемого объема можно использовать различные методы, чтобы обработать этот набор результатов. В этом примере мы используем объект cursor как итератор. Первый столбец в строке сохранен в переменной first_name, второй в last_name, третий в hire_date.

Мы печатаем результат, форматируя вывод, используя встроенную функцию Python format(). Отметьте, что hire_date был преобразован автоматически Connector/Python в объект Python datetime.date. Это означает, что мы можем легко отформатировать дату в более читаемой форме.

Вывод должен быть чем-то вроде этого:

...
Wilharm, LiMin was hired on 16 Dec 1999
Wielonsky, Lalit was hired on 16 Dec 1999
Kamble, Dannz was hired on 18 Dec 1999
DuBourdieux, Zhongwei was hired on 19 Dec 1999
Fujisawa, Rosita was hired on 20 Dec 1999
...

Поиск

 

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

Вы можете направить письмо администратору этой странички, Алексею Паутову. mailto:alexey.v.pautov@mail.ru