Isso parece ser um problema ao usar
jaydebeapi
com jpype
. Eu posso reproduzir isso ao conectar a um banco de dados Oracle da mesma maneira que você faz (no meu caso Oracle 11gR2, mas já que você está usando ojdbc8.jar
, acho que também acontece com outras versões). Existem diferentes maneiras de você resolver isso:
Alterar sua conexão
Como o erro parece ocorrer apenas em uma combinação específica de pacotes, a coisa mais sensata a fazer é tentar evitá-los e, portanto, o erro por completo.
-
Alternativa 1:usejaydebeapi
semjpype
:
Conforme observado, só observo isso ao usarjaydebeapi
comjpype
. No entanto, no meu caso,jpype
não é necessário. Eu tenho o.jar
arquivo localmente e minha conexão funciona bem sem ele:
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()
No meu caso, isso funciona bem e cria os dataframes normalmente.
-
Alternativa 2:usecx_Oracle
em vez disso:
O problema também não ocorre se eu usarcx_Oracle
para se conectar ao banco de dados 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()
Observação:paracx_Oracle
para funcionar você precisa ter o Oracle Instant Client instalado e configurado corretamente (consulte, por exemplo, documentação do cx_Oracle para Ubuntu ).
Corrigir dataframe após o fato:
Se, por algum motivo, você não puder usar as alternativas de conexão acima, também poderá transformar seu dataframe.
-
Alternativa 3:unir entradas de tupla:
Você pode usar''.join()
para converter tuplas em strings . Você precisa fazer isso para as entradas e os nomes das colunas.
# 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:altere o tipo de colunas:
Mudando odtype
de uma coluna afetada deobject
parastring
, todas as entradas também serão convertidas. Observe que isso pode ter efeitos colaterais indesejados, como, por exemplo, alterandoNone
valores para a string<N/A>
. Além disso, você terá que renomear os títulos das colunas separadamente, como acima.
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 esses devem produzir mais ou menos o mesmo
df
no final (além dos dtypes
e possível substituição de None
valores):+---+---------+---------+---------+
| | COLUMN1 | COLUMN2 | COLUMN3 |
+---+---------+---------+---------+
| 1 | test | test2 | 1 |
+---+---------+---------+---------+
| 2 | foo | bar | 100 |
+---+---------+---------+---------+