Questo sembra essere un problema quando si utilizza jaydebeapi
con jpype
. Posso riprodurlo quando mi collego a un db Oracle nello stesso modo in cui lo fai (nel mio caso Oracle 11gR2, ma dal momento che stai usando ojdbc8.jar
, suppongo che succeda anche con altre versioni).
Esistono diversi modi per risolvere questo problema:
Cambia la tua connessione
Poiché l'errore sembra verificarsi solo in una specifica combinazione di pacchetti, la cosa più sensata da fare è cercare di evitare questi e quindi l'errore del tutto.
-
Alternativa 1:usa
jaydebeapi
senzajpype
:Come notato, lo osservo solo quando utilizzo
jaydebeapi
conjpype
. Tuttavia, nel mio caso,jpype
non è affatto necessario. Ho il.jar
file localmente e la mia connessione funziona bene senza di esso: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()
Nel mio caso, funziona bene e crea normalmente i frame di dati.
-
Alternativa 2:usa
cx_Oracle
invece:Il problema inoltre non si verifica se utilizzo
cx_Oracle
per connettersi al db 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:per
cx_Oracle
per funzionare devi avere il Oracle Instant Client installato e configurato correttamente (vedi ad es. documentazione cx_Oracle per Ubuntu ).
Correggi dataframe dopo il fatto:
Se per qualche motivo non puoi utilizzare le alternative di connessione di cui sopra, puoi anche trasformare il tuo dataframe.
-
Alternativa 3:unisci le voci della tupla:
Puoi usare
''.join()
per convertire tuple in stringhe . Devi farlo per le voci e i nomi delle colonne.# 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:cambia dtype di colonne:
Modificando il
dtype
di una colonna interessata daobject
astring
, verranno convertite anche tutte le voci. Tieni presente che ciò potrebbe avere effetti collaterali indesiderati, come ad es. modificandoNone
valori alla stringa<N/A>
. Inoltre, dovrai rinominare le intestazioni delle colonne separatamente, come sopra.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)
Tutti questi dovrebbero produrre più o meno lo stesso df
alla fine (a parte i dtypes
ed eventuale sostituzione di None
valori):
+---+---------+---------+---------+
| | COLUMN1 | COLUMN2 | COLUMN3 |
+---+---------+---------+---------+
| 1 | test | test2 | 1 |
+---+---------+---------+---------+
| 2 | foo | bar | 100 |
+---+---------+---------+---------+