Python глазами DBA::Журнал СА 7.2003
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Наука и технологии
Подписка
Где купить
Авторам
Рекламодателям
Архив номеров
Контакты
   

  Опросы
  Статьи

Электронный документооборот  

5 способов повысить безопасность электронной подписи

Область применения технологий электронной подписи с каждым годом расширяется. Все больше задач

 Читать далее...

Рынок труда  

Системные администраторы по-прежнему востребованы и незаменимы

Системные администраторы, практически, есть везде. Порой их не видно и не слышно,

 Читать далее...

Учебные центры  

Карьерные мечты нужно воплощать! А мы поможем

Школа Bell Integrator открывает свои двери для всех, кто хочет освоить перспективную

 Читать далее...

Гость номера  

Дмитрий Галов: «Нельзя сказать, что люди становятся доверчивее, скорее эволюционирует ландшафт киберугроз»

Использование мобильных устройств растет. А вместе с ними быстро растет количество мобильных

 Читать далее...

Прошу слова  

Твердая рука в бархатной перчатке: принципы soft skills

Лауреат Нобелевской премии, специалист по рынку труда, профессор Лондонской школы экономики Кристофер

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 9947
Комментарии: 0
Потоковая обработка данных

 Читать далее...

19.03.2018г.
Просмотров: 8160
Комментарии: 0
Релевантный поиск с использованием Elasticsearch и Solr

 Читать далее...

19.03.2018г.
Просмотров: 8262
Комментарии: 0
Конкурентное программирование на SCALA

 Читать далее...

19.03.2018г.
Просмотров: 5228
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 5915
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

Друзья сайта  

 Python глазами DBA

Архив номеров / 2003 / Выпуск №7 (8) / Python глазами DBA

Рубрика: Программирование /  Анализ данных

ОЛЕГ ПОПОВ

Python глазами DBA

Почему, собственно, Python

Администраторы БД очень часто нуждаются в инструментах для автоматизации разной рутинной работы, например: загрузка, преобразования данных в разного рода форматы или сбор и анализ различной статистики. Для меня в свое время такой палочкой-выручалочкой стал Perl.

Через некоторое время я набрел на Python. Что я могу сказать после года знакомства: практичный и полезный инструмент.

Достоинства языка Python:

  • Многоплатформенность и масштабируемость: работает на большинстве известных программно-аппаратных платформ от PDA до CRAY и IBM 390.
  • Гармоничная архитектура языка:
    • Простой и удобный для понимания логики программ синтаксис.
    • Встроенные структуры данных: списки, кортежи, словари.
    • Огромное количество библиотек:
      • XML-парсеры;GUI (Win32, GTK/GNOME, KDE/QT, TK, FOX, WXWindows);
      • Сетевые протоколы;
      • Разработка веб-приложений.
    • Переносимость кода между различными платформами.
    • Мощные интерфейсы к конкретным ОС (особенно к Linux/UNIX и win32).
    • Поддержка разных стилей программирования: процедурного, объектного, функционального.
    • Встроенная поддержка Unicode и множества национальных кодировок (включая 5 русских).
    • Возможность писать самодокументированные программы и автоматическая генерация документации на модули.

С чем в действительности сталкивается программист при использовании Python – это простой и ясный синтаксис. Я ловлю себя часто на мысли, что просмотр чужого кода зачастую не требует значительного напряжения. И здесь помогает то, что отступы являются частью синтаксиса и определяют вложенность операторов.

Библиотеки зачастую имеют очень лаконичную документацию, но этого достаточно, так как API очень выразительны и внятны.

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

Для работы с RDBMS Oracle существует несколько различных модулей для Python, использующих разные механизмы:

  • ODBC (Win32, Linux)
  • DCOM (Win32)
  • PERL_DBI (Win32, Linux, Solaris, HP-UX, AIX)
  • NATIVE API (Win32, Linux, Solaris, HP-UX, AIX)

Более подробную информацию вы можете найти на www.python.org.

Выполняем простой запрос

Я предпочитаю использовать модуль cx_Oracle, который был проверен мною в ОС NT и Linux (автор Anthony Tuininga утверждает, что он работает в Solaris и, похоже, на всех UNIX-подобных ОС должен также работать). В основном этот модуль следует спецификации Python Database API 2.0 и поддерживает работу с RDBMS Oracle версий 8.1-9.xx.

Для быстрого погружения в предмет я приведу фрагменты кода, демонстрирующего основные приемы использования модуля.

try:

    import cx_Oracle

except ImportError,info:

    print "Import Error:",info

    sys.exit()

if cx_Oracle.version<"3.0":

    print "Very old version of cx_Oracle :",cx_Oracle.version

    sys.exit()

В этом фрагменте демонстрируется безопасная загрузка модуля cx_Oracle и проверка версии. (Надеюсь, элегантность синтаксиса все-таки заметили).

Далее создадим экземпляр класса connect – именно этот объект и обеспечивает взаимодействие с сервером Oracle.

try:

my_connection=cx_Oracle.connect("system/manager@test_db")

except cx_Oracle.DatabaseError,info:

    print "Logon  Error:",info

    exit(0)

Теперь создаем курсор и выполняем запрос:

my_cursor=my_connection.cursor()

try:

my_cursor.execute("""

SELECT OWNER,SEGMENT_TYPE,TABLESPACE_NAME,SUM(BLOCKS)SIZE_BLOCKS, COUNT(*) SIZE_EXTENTS FROM DBA_EXTENTS

GROUP BY OWNER,SEGMENT_TYPE,TABLESPACE_NAME

    """)

except cx_Oracle.DatabaseError,info:

    print "SQL Error:",info

    exit(0)

: (name, type_code, display_size, internal_size, precision, scale, null_ok).

Далее следует форматированный вывод на stdout (почти как printf в языке C).

print

print "Database:",my_connection.tnsentry

print

print "Used space by owner, object type, tablespace "

print "-------------------------------------------------"

title_mask=("%-16s","%-16s","%-16s","%-8s","%-8s")

i=0

    i=1+i

print ""

print "-------------------------------------------------"

row_mask="%-16s %-16s %-16s %8.0f %8.0f "

for recordset in my_cursor.fetchall():

print row_mask%recordset

В результате мы увидим что-то вроде:

Database: testdb

Used space by owner, object type, tablespace

-------------------------------------------------------------

OWNER   SEGMENT_TYPE TABLESPACE_NAME SIZE_BLOCKS SIZE_EXTENTS

-------------------------------------------------------------

ADU2     INDEX        USERS                 784       25

ADU2     TABLE        USERS                 512       24

ADUGKS   INDEX        DEVELOP_DATA          984      123

ADUGKS   TABLE        DEVELOP_DATA          664       83

ADUGPA   INDEX        USERS                 784       25

ADUGPA   TABLE        USERS                 496       23

AGNKS_SG INDEX        USERS                 352       22

AGNKS_SG TABLE        USERS                 240       15

ATU      INDEX        USERS                3968      244

ATU      TABLE        DEVELOP_DATA            8        1

ATU      TABLE        USERS                2688      160

ATU1     INDEX        DEVELOP_DATA         1600      200

ATU1     INDEX        USERS                 608       38

ATU1     TABLE        DEVELOP_DATA         1032      129

ATU1     TABLE        USERS                 544       34

BUX      INDEX        DEVELOP_DATA           64        8

BUX      TABLE        DEVELOP_DATA         1736      217

DISP     INDEX        USERS                 400       25

DISP     TABLE        USERS                 528       33

EPE      INDEX        USERS                  80        5

EPE      TABLE        USERS                  48        3

EXZ      INDEX        USERS                1088       61

EXZ      TABLE        DEVELOP_DATA            8        1

EXZ      TABLE        USERS                 832       41

Запросы с параметрами

Согласно спецификации Python Database API 2.0 для выполнения запросов с параметрами каждый модуль должен реализовывать переменную paramstyle, которая определяет, каким образом будут передаваться параметры запросов. Текущая версия cx_Oracle(3.0) поддерживает режим "named", то есть в модуле установлена переменная cx_Oracle.paramstyle="named" и можно создавать конструкции в запросах в виде:

select *  from all_users where USERNAME LIKE :S

При этом связывание параметров запроса со значениями можно выполнить двумя способами.

Именованый параметeр метода exec:

cursor2.execute("select *  from all_users where USERNAME LIKE :S ",S="S%")

Словарь {":переменная":значение,...}:

cursor2.execute("select *  from all_users where USERNAME LIKE :S ",{":S":"S%"})

Анонимные блоки PL/SQL

В некоторых случаях очень удобно использовать нестандартные средства сервера: для Oracle таким нестандартным, но очень удобным механизмом является возможность исполнения анонимных блоков PL/SQL. Модуль сx_Oracle реализует этот механизм, который, естественно, не описан в спецификации Python Database API 2.0.

Чтобы связать переменные блока PL/SQL c переменными языка Python, в модуле сx_Oracle реализован класс var. Экземпляр можно создать следующим образом:

var=my_cursor.var(cx_Oracle.DATETIME)

Конструктор my_cursor.var(...) в качестве параметра требует указать тип создаваемой переменной. Варианты:

  • BINARY
  • DATETIME
  • FIXEDCHAR
  • LONGBINARY
  • LONGSTRING
  • NUMBER
  • ROWID
  • STRING

var=my_cursor.var(cx_Oracle.DATETIME)

try:

    my_cursor.execute("""begin

    SELECT SYSDATE INTO :p_Value from dual;

    end;""",p_Value = var)  

except cx_Oracle.DatabaseError,info:

    print "SQL Error:",info

    exit(0)

Очевидно, что теперь var содержит текущее время сервера. Доступ к значениям переменной выполняется с помощью метода var.getvalue():

CDATE=var.getvalue()

print "Date: %02u/%02u/%4u"%(CDATE.day,CDATE.month,CDATE.year)

print "Time: %02u:%02u:%02u"%(CDATE.hour,CDATE.minute,CDATE.second)

Этот пример демонстрирует также и форматирование даты и времени для экземпляра var. В результате напечатается нечто вроде:

Date: 12/05/2003

Time: 16:42:54

В связи с тем, что работа с типами времени и даты внутри сервера Oracle реализована особенным образом (независимо от ОС), модуль сx_Oracle реализует следующие функции для для преобразования значений дат и времени:

  • Date( year, month, day)
  • DateFromTicks( ticks)
  • Time( hour, minute, second)
  • TimeFromTicks( ticks)
  • Timestamp( year, month, day, hour, minute, second)
  • TimestampFromTicks( ticks)

var=my_cursor.var(cx_Oracle.DATETIME)

var.setvalue(0,cx_Oracle.Date( 2002, 02,12))

CDATE=var.getvalue()

print"Date:%02u/%02u/%4u"%(CDATE.day,CDATE.month,CDATE.year)

print"Time:%02u:%02u:%02u"%(CDATE.hour,CDATE.minute,CDATE.second)

Результат будет следующий:

Date: 12/02/2002

Time: 00:00:00

Ссылки:

  1. http://computronix.com/utilities.shtml
  2. http://www.python.org/topics/database/DatabaseAPI-2.0.html

Листинг 1

Выполняем простой запрос:

""

cx_Oracle demo

simple query

"""

__AUTHOR__='POPOV O.'

__COPYRIGHT__='POPOV O. 2002 Samara, Russia'

from sys import exit

try:

    import cx_Oracle

except ImportError,info:

    print "Import Error:",info

    sys.exit()

if cx_Oracle.version<'3.0':

    print "Very old version of cx_Oracle :",cx_Oracle.version

    sys.exit()

try:

    my_connection=cx_Oracle.connect('system/gasdba@sqlmt')

except cx_Oracle.DatabaseError,info:

    print "Logon  Error:",info

    exit(0)

my_cursor=my_connection.cursor()

try:

 my_cursor.execute("""

 SELECT OWNER,SEGMENT_TYPE,TABLESPACE_NAME,SUM(BLOCKS)SIZE_BLOCKS,COUNT(*) SIZE_EXTENTS FROM DBA_EXTENTS

 GROUP BY OWNER,SEGMENT_TYPE,TABLESPACE_NAME

    """)

except cx_Oracle.DatabaseError,info:

    print "SQL Error:",info

    exit(0)

print

print 'Database:',my_connection.tnsentry

print

print "Used space by owner, object type, tablespace "

print "--------------------------------------------------"

title_mask=('%-16s','%-16s','%-16s','%-8s','%-8s')

i=0

for column_description in my_cursor.description:

    print title_mask[i]%column_description[0],

    i=1+i

print ''

print "--------------------------------------------------"

row_mask='%-16s %-16s %-16s %8.0f %8.0f '

for recordset in my_cursor.fetchall():

print row_mask%recordset

for column_description in my_cursor.description:

    print column_description

Листинг 2

Запрос с параметрами:

""

cx_Oracle demo

query with parameters

"""

__AUTHOR__='POPOV O.'

__COPYRIGHT__='POPOV O. 2002 Samara, Russia'

from sys import exit

try:

    import cx_Oracle

except ImportError,info:

    print "Import Error:",info

    sys.exit()

if cx_Oracle.version<'3.0':

    print "Very old version of cx_Oracle :",cx_Oracle.version

    sys.exit()

try:

    my_connection=cx_Oracle.connect('system/manager@test_db')

except cx_Oracle.DatabaseError,info:

    print "Logon  Error:",info

    exit(0)

my_cursor=my_connection.cursor()

try:

    my_cursor.execute("""

    SELECT OWNER,SEGMENT_TYPE,TABLESPACE_NAME, SUM(BLOCKS)SIZE_BLOCKS,COUNT(*) SIZE_EXTENTS FROM DBA_EXTENTS

        WHERE OWNER LIKE :S

    GROUP BY OWNER,SEGMENT_TYPE,TABLESPACE_NAME

    """,S='SYS%')

except cx_Oracle.DatabaseError,info:

    print "SQL Error:",info

    exit(0)

print

print 'Database:',my_connection.tnsentry

print

print "Used space by owner, object type, tablespace "

print "---------------------------------------------------"

title_mask=('%-16s','%-16s','%-16s','%-8s','%-8s')

i=0

for column_description in my_cursor.description:

    print title_mask[i]%column_description[0],

    i=1+i

print ''

print "----------------------------------------------------"

row_mask='%-16s %-16s %-16s %8.0f %8.0f '

for recordset in my_cursor.fetchall():

print row_mask%recordset


Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-41
Fax: (499) 277-12-45
E-mail: sa@samag.ru