Esto parece ser un problema cuando se usa jaydebeapi
con jpype
. Puedo reproducir esto cuando me conecto a una base de datos Oracle de la misma manera que lo haces tú (en mi caso, Oracle 11gR2, pero como estás usando ojdbc8.jar
, supongo que también pasa con otras versiones).
Hay diferentes formas de resolver esto:
Cambia tu conexión
Dado que el error solo parece ocurrir en una combinación específica de paquetes, lo más sensato es tratar de evitarlos y, por lo tanto, el error por completo.
-
Alternativa 1:Usar
jaydebeapi
sinjpype
:Como se señaló, solo observo esto cuando uso
jaydebeapi
conjpype
. Sin embargo, en mi caso,jpype
no es necesario en absoluto. Tengo el.jar
archivo localmente y mi conexión funciona bien sin él:import jaydebeapi as jdba import pandas as pd import os db_host = 'db.host.com' db_port = 1521 db_sid = 'YOURSID' jar=os.getcwd()+'/ojdbc6.jar' conn = jdba.connect('oracle.jdbc.driver.OracleDriver', 'jdbc:oracle:thin:@' + db_host + ':' + str(db_port) + ':' + db_sid, {'user': 'USERNAME', 'password': 'PASSWORD'}, jar ) df_jay = pd.read_sql('SELECT * FROM YOURSID.table1', conn) conn.close()
En mi caso, esto funciona bien y crea los marcos de datos normalmente.
-
Alternativa 2:Usar
cx_Oracle
en cambio:El problema tampoco ocurre si uso
cx_Oracle
para conectarse a la base de datos de Oracle:import cx_Oracle import pandas as pd import os db_host = 'db.host.com' db_port = 1521 db_sid = 'YOURSID' dsn_tns = cx_Oracle.makedsn(db_host, db_port, db_sid) cx_conn = cx_Oracle.connect('USERNAME', 'PASSWORD', dsn_tns) df_cxo = pd.read_sql('SELECT * FROM YOURSID.table1', con=cx_conn) cx_conn.close()
Nota:para
cx_Oracle
para trabajar tienes que tener el Oracle Instant Client instalado y configurado correctamente (consulte, por ejemplo, cx_Documentación de Oracle para Ubuntu ).
Corregir marco de datos después del hecho:
Si por algún motivo no puede utilizar las alternativas de conexión anteriores, también puede transformar su marco de datos.
-
Alternativa 3:unir entradas de tupla:
Puedes usar
''.join()
para convertir tuplas en cadenas . Debe hacer esto para las entradas y los nombres de las columnas.# for all entries that are not None, join the tuples for col in df.select_dtypes(include=['object']).columns: df[col] = df[col].apply(lambda x: ''.join(x) if x is not None else x) # also rename the column headings in the same way df.rename(columns=lambda x: ''.join(x) if x is not None else x, inplace=True)
-
Alternativa 4:cambiar el tipo de columnas:
Cambiando el
dtype
de una columna afectada deobject
astring
, todas las entradas también se convertirán. Tenga en cuenta que esto puede tener efectos secundarios no deseados, como p. cambiandoNone
valores a la cadena<N/A>
. Además, tendrá que cambiar el nombre de los encabezados de las columnas por separado, como se indicó anteriormente.for col in df.select_dtypes(include=['object']).columns: df[col] = df[col].astype('string') # again, rename headings df.rename(columns=lambda x: ''.join(x) if x is not None else x, inplace=True)
Todos estos deberían producir más o menos el mismo df
al final (aparte de los dtypes
y posible reemplazo de None
valores):
+---+---------+---------+---------+
| | COLUMN1 | COLUMN2 | COLUMN3 |
+---+---------+---------+---------+
| 1 | test | test2 | 1 |
+---+---------+---------+---------+
| 2 | foo | bar | 100 |
+---+---------+---------+---------+