SubscribeMainXMLTagsEditHistoryDiscussion

  1. Introducción
  2. Instalando el cliente de ORACLE
  3. Compilando la extensión cx_Oracle
  4. Probando una consulta
  5. Retornando un valor
  6. Haciendo un insert
  7. Referencias

Introducción

En este documento se muestra como realizar una consulta a una base de datos usando el motor ORACLE, desde el lenguaje de programación Python.

Seguramente hay varias opciones para esto. En este documento se usa el Instant Client. Las instrucciones fueron probadas en Debian GNU/Linux. Es probable que sean útiles para Ubuntu y para otras distribuciones.

El documento fue escrito inicialmente por Nelson. Recuerde esta es una Wiki, por lo que si ve errores en este documento, puede editar y corregirlos.

Es mejor usar una base de datos con código fuente libre (como PostgreSQL o MySQL), pero si la mejor opción es ORACLE (o la que toca implementar) acá hay unas instrucciones que pueden ser útiles.

Instalando el cliente de ORACLE

El primer paso es bajar el Instant Client de ORACLE (requiere registro gratuito). Los archivos del cliente se descomprimen en un directorio. En este ejemplo, usaremos la variable de entorno $INSTANT para denotar el $PATH en el que se descomprimen. Se requiere usar el paquete unzip.

$ unzip instantclient-basic-linux32-10.2.0.3-20061115.zip
Archive:  instantclient-basic-linux32-10.2.0.3-20061115.zip
  inflating: instantclient_10_2/classes12.jar
  inflating: instantclient_10_2/genezi
  #más archivos...

El kit de desarrollo:

$ unzip  instantclient-sdk-linux32-10.2.0.3-20061115.zip
Archive:  instantclient-sdk-linux32-10.2.0.3-20061115.zip
   creating: instantclient_10_2/sdk/
   creating: instantclient_10_2/sdk/include/
  inflating: instantclient_10_2/sdk/include/occi.h
  inflating: instantclient_10_2/sdk/include/occiCommon.h
  #más archivos

Ahora instanciamos la variable de entorno $INSTANT, que usamos para hacer que estas instrucciones no dependan de la ruta específica de la instalación.

export INSTANT=/$HOME/python-oracle/instantclient_10_2/

Compilando la extensión cx_Oracle

Ahora se descarga la extensión cx_Oracle, que permite realizar la conexión a la base de datos desde Python. Se requiere instalar el paquete python-dev.

sudo aptitude install python-dev
# Es necesario poner este enlace para que funcione la compilación. Si no, sale el error
# /usr/bin/ld: cannot find -lclntsh
pushd $INSTANT && ln -s libclntsh.so.10.1 libclntsh.so && popd
export ORACLE_HOME=$INSTANT
tar xzvf cx_Oracle-X.X.X.tar.gz # la extensión bajada (probamos con la versión 4.3.1)
cd cx_Oracle-X.X.X
python setup.py build

Al terminar la compilación, la extensión compilada queda en el directorio cx_Oracle-X.X.X/build/lib.linux-i686-2.4/ y el nombre del archivo es cx_Oracle.so. El nombre del directorio depende de su plataforma. Para probarla se puede instalar para que esté disponible para todos los usuarios del sistema (ejecutando Python python setup.py install como root).

Haremos la prueba sin instalar la extensión. La copiaremos a la ruta en la que se va a incluir.

LD_LIBRARY_PATH=$INSTANT ./test.py
cp cx_Oracle-X.X.X/build/lib.linux-i686-2.4/cx_Oracle.so .

Probando una consulta

El siguiente es el código de un archivo que llamaremos test.py:

#!/usr/bin/env python

import cx_Oracle, sys

dsn = cx_Oracle.makedsn('127.0.0.1', 1521, 'BASEDATOS')
connection = cx_Oracle.connect('USUARIO', 'PASSWORD', dsn)
cursor = connection.cursor()

cursor = connection.cursor()
cursor.arraysize = 50

cursor.execute("""select columna1, columna2 from tabla  where rownum < :arg_1""", arg_1 = 3)

for c1, c2 in cursor.fetchall():
  print 'Values:', c1, c2

Para ejecutar el script, se requiere tener asignadas las variables de entorno LD_LIBRARY_PATH y ORACLE_HOME. Este el resultado de la prueba:

$ ORACLE_HOME=$INSTANT  LD_LIBRARY_PATH=$INSTANT python test.py
Values: 514 985
Values: 379 1038

Retornando un valor

En este mensaje hay un ejemplo en el que explican como retornar un valor, y esto es útil en ciertos casos. Por ejemplo en el siguiente ejemplo se requiere el valor de una secuencia, de las que se usan como claves primarias.

                                                                                             
 idVar = cursor.var(cx_Oracle.NUMBER)                                                
                                                                                               
  q = """BEGIN                                                                                
  select carg_arch.CAR_ARCH_ARCHIVOS_SECUE.nextval into :id from dual;                        
  END;"""                                                                                     
                                                                                                
  cursor.execute(q, id = idVar)                                                       
  print idVar.getvalue()    

TODO: ¿Es esto realmente necesario? ¿Hay un atajo?.

Haciendo un insert

   q = "insert into table(fielda, fieldb) values(:idx, 'something')"; 
   cursor.execute(q, idx=2) 
   connection.commit()

No olvide hacer el commit.

Referencias

Last update: 2007-06-12 (Rev 11659)

svnwiki $Rev: 14721 $