Това изглежда е проблем при използване на jaydebeapi
с jpype
. Мога да възпроизведа това, когато се свързвам с Oracle db по същия начин, както вие (в моя случай Oracle 11gR2, но тъй като използвате ojdbc8.jar
, предполагам, че се случва и с други версии).
Има различни начини, по които можете да разрешите това:
Променете връзката си
Тъй като изглежда, че грешката се появява само в конкретна комбинация от пакети, най-разумното нещо, което трябва да направите, е да се опитате да ги избегнете и следователно грешката като цяло.
-
Алтернатива 1:Използвайте
jaydebeapi
безjpype
:Както беше отбелязано, наблюдавам това само когато използвам
jaydebeapi
сjpype
. В моя случай обаче,jpype
изобщо не е необходимо. Имам.jar
файл локално и връзката ми работи добре без него: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()
В моя случай това работи добре и създава рамки с данни нормално.
-
Алтернатива 2:Използвайте
cx_Oracle
вместо това:Проблемът също не възниква, ако използвам
cx_Oracle
за да се свържете с Oracle db: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()
Забележка:За
cx_Oracle
за да работите, трябва да имате Oracle Instant Client инсталиран и правилно настроен (вижте напр. cx_Oracle документация за Ubuntu ).
Коригирайте рамката с данни след факта:
Ако по някаква причина не можете да използвате горните алтернативи за свързване, можете също да преобразувате вашата рамка с данни.
-
Алтернатива 3:обединяване на записи на кортежи:
Можете да използвате
''.join()
за конвертиране на кортежи в низове . Трябва да направите това за записите и имената на колоните.# 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)
-
Алтернатива 4:промяна на dtype на колоните:
Чрез промяна на
dtype
на засегната колона отobject
къмstring
, всички записи също ще бъдат конвертирани. Имайте предвид, че това може да има нежелани странични ефекти, като напр. промяна наNone
стойности към низа<N/A>
. Освен това ще трябва да преименувате заглавията на колоните отделно, както по-горе.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)
Всички те трябва да дадат повече или по-малко същия df
в крайна сметка (с изключение на dtypes
и възможна замяна на None
стойности):
+---+---------+---------+---------+
| | COLUMN1 | COLUMN2 | COLUMN3 |
+---+---------+---------+---------+
| 1 | test | test2 | 1 |
+---+---------+---------+---------+
| 2 | foo | bar | 100 |
+---+---------+---------+---------+