Wydaje się to być problemem podczas korzystania z jaydebeapi
z jpype
. Mogę to odtworzyć podczas łączenia się z bazą danych Oracle w taki sam sposób, jak ty (w moim przypadku Oracle 11gR2, ale ponieważ używasz ojdbc8.jar
, wydaje mi się, że dzieje się tak również z innymi wersjami).
Można to rozwiązać na różne sposoby:
Zmień połączenie
Ponieważ błąd wydaje się występować tylko w określonej kombinacji pakietów, najrozsądniejszą rzeczą do zrobienia jest próba ich uniknięcia, a tym samym całkowitego błędu.
-
Alternatywna 1:Użyj
jaydebeapi
bezjpype
:Jak wspomniano, obserwuję to tylko podczas używania
jaydebeapi
zjpype
. Jednak w moim przypadkujpype
w ogóle nie jest potrzebna. Mam plik.jar
plik lokalnie, a moje połączenie działa bez niego: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()
W moim przypadku działa to dobrze i normalnie tworzy ramki danych.
-
Alternatywna 2:użyj
cx_Oracle
zamiast tego:Problem nie występuje również, jeśli używam
cx_Oracle
aby połączyć się z bazą danych 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()
Uwaga:dla
cx_Oracle
aby pracować, musisz mieć Oracle Instant Client zainstalowane i poprawnie skonfigurowane (patrz np. Dokumentacja cx_Oracle dla Ubuntu ).
Napraw ramkę danych po fakcie:
Jeśli z jakiegoś powodu nie możesz użyć powyższych alternatyw połączeń, możesz również przekształcić ramkę danych.
-
Alternatywna 3:połącz wpisy krotek:
Możesz użyć
''.join()
do konwertowania krotek na ciągi . Musisz to zrobić dla wpisów i nazw kolumn.# 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)
-
Alternatywnie 4:zmień typ kolumn:
Zmieniając
dtype
danej kolumny zobject
dostring
, wszystkie wpisy również zostaną przekonwertowane. Pamiętaj, że może to mieć niepożądane skutki uboczne, takie jak np. zmianaNone
wartości do ciągu<N/A>
. Ponadto będziesz musiał osobno zmienić nazwy nagłówków kolumn, jak powyżej.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)
Wszystkie te powinny dać mniej więcej to samo df
na końcu (oprócz dtypes
i możliwe zastąpienie None
wartości):
+---+---------+---------+---------+
| | COLUMN1 | COLUMN2 | COLUMN3 |
+---+---------+---------+---------+
| 1 | test | test2 | 1 |
+---+---------+---------+---------+
| 2 | foo | bar | 100 |
+---+---------+---------+---------+