Как стать автором
Обновить

Доступ к BLOB-полям БД Oracle из Python

Недавно у меня появилась задача со следующими исходными данными:
  • Необходимо выгрузить на диск данные из blob-полей таблицы;
  • СУБД Oracle установлена на отдельном сервере;
  • Данные должны выгружаться на локальную машину с операционной системой Ubuntu 9.10.

Решено было написать скрипт на любимом языке — Python. Но так как Python, по умолчанию, не умеет работать с Oracle, нужно его этому обучить.

Установка библиотек и подготовка к работе


Для работы с Oracle потребуются следующие библиотеки cx_Oracle и Oracle Instant Client. Но так как ни той ни другой библиотеки в виде deb-пакета я не нашел, пришлось делать их самому.

Шаг 1. Сначала устанавливаем пакет alien, который умеет преобразовывать rpm-пакеты в deb:

sudo apt-get install alien

Шаг 2. Идем на сайт cx_Oracle и скачиваем версию, подходящую Вам:

У меня Python 2.6 (для проверки версии выполнить нужно команду python -V) и Oracle 11 версии, поэтому я выбрал версию CentOS 5 i386 RPM (Oracle 11g, UNICODE, Python 2.6)

Шаг 3. На сайте Oracle скачиваем Oracle Instant Client:

Шаг 4. Устанавливаем rpm-пакеты с помощью alien:

sudo alien -i cx_Oracle-5.0.3-11g-unicode-py26-1.i386.rpm

sudo alien -i oracle-instantclient11.2-basic-11.2.0.1.0-1.i386.rpm


Шаг 5. Прописываем пути до библиотек:

export ORACLE_HOME=/usr/lib/oracle/11.2/client

export LD_LIBRARY_PATH=$ORACLE_HOME/lib

export PATH=$PATH:$ORACLE_HOME/bin


Шаг 6. Прописываем адрес сервера БД в файле tnsnames.ora. Обычно этот файл находится в директории $ORACLE_HOME/network/admin.

Создаем файл tnsnames.ora в директории $ORACLE_HOME/network/admin:

mkdir $ORACLE_HOME/network

mkdir $ORACLE_HOME/network/admin

touch $ORACLE_HOME/network/admin/tnsnames.ora


И записываем туда следующий код:

название_соединения =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = адрес_сервера)(PORT = порт))
)
(CONNECT_DATA =
(SERVICE_NAME = имя_инстанса)
)
)


Шаг 6. Устанавливаем библиотеку libaio1, которая требуется клиенту Oracle:

sudo apt-get install libaio1

Шаг 7. Пробуем подключиться к Oracle

Экспортируем NLS_LANG для правильного отображения русских символов.

export NLS_LANG=RUSSIAN_CIS.AL32UTF8

Подключаемся:

sqlplus <user_name>@<название соединения>

Если появилось приветствие Oracle, то все настроено верно.

Шаг 8. Создаем тестовую таблицу

CREATE TABLE TestTable (id NUMBER, blobfield BLOB);

На этом подготовка завершена.

Пишем скрипт


Я приведу текст простейшего скрипта, который загружает данные в таблицу и выгружает их на диск.

Copy Source | Copy HTML
  1. # -*- coding: utf-8 -*-
  2.  
  3. import cx_Oracle
  4.  
  5. # Создаем массив файлов, которые будут загружены в БД. 
  6. # Я кинул файлы в директорию со скриптом, чтобы не прописывать абсолютные пути
  7. inputs = []
  8. inputs.append(open('DSC_0035.jpg', 'rb'))
  9. inputs.append(open('DSC_0036.jpg', 'rb'))
  10.  
  11. # Подключаемся к БД
  12. dbconn = cx_Oracle.connect('user', 'password', 'host_name/service_name')
  13. dbconn.autocommit = True
  14.  
  15. cur = dbconn.cursor()
  16. cur.setinputsizes(blobfield=cx_Oracle.BLOB)
  17.  
  18. # Записываем данные в БД
  19. i = 1
  20. for input in inputs:
  21.     file = input.read()
  22.     cur.execute("INSERT INTO TestTable (id, blobfield) VALUES(:id, :blobfield)", {'id':i, 'blobfield':file})
  23.     input.close()
  24.     i += 1
  25.  
  26. # Забираем данные
  27. cur.execute('select id, blobfield from TestTable')
  28.  
  29. results = cur.fetchall()
  30.  
  31. for id, blobfield in results:
  32.     output = open(str(id)+'.jpg', 'wb')
  33.     blob = blobfield.read()
  34.     output.write(blob)
  35.     output.close()
  36.  
  37. # Закрываем соединение
  38. dbconn.close()

После выполнения в директории скрипта должны появиться файлы (1.jpg и 2.jpg), являющиеся копиями файлов DSC_0035.jpg и DSC_0035.jpg.

Ну вот, собственно, и все =)
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.