これは、jaydebeapi
を使用するときに問題になるようです jpype
を使用 。これは、Oracleデータベースに接続するときに同じ方法で再現できます(私の場合は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データベースに接続するには: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 InstantClient が必要です。 インストールされ、適切にセットアップされている(例:Ubuntuのcx_Oracleドキュメント 。
事後のデータフレームを修正:
何らかの理由で上記の代替接続を使用できない場合は、データフレームを変換することもできます。
-
代替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 |
+---+---------+---------+---------+