2016-06-01 25 views
1

CSVで読み込むPythonスクリプトで作業していますが、cx_Oracleを使用して内容をOracleデータベースに書き出します。これまでのところ、私は次のエラーを取得してきた:cx_Oracleを使用してUnicodeテキストを書き込めません

明らか
UnicodeEncodeError: 'ascii' codec can't encode character '\xa0' in position 1369: ordinal not in range(128) 

、cx_OracleはASCIIにUnicode文字を変換しようとしている、それが働いていません。

少数の明確化のポイント:

  • 私はCSVファイルは、私がNVARCHAR2フィールドを使用しているUTF-8でエンコードされ、open('all.csv', encoding='utf8')
  • のように開かれているのPython 3.4.3
  • を使用していますNLS_NCHAR_CHARACTERSETAL16UTF16に設定されています。 NLS_CHARACTERSETWE8MSWIN1252ですが、私はNVARCHAR2を使用しているので、これは関係ないはずです。
  • 私は.AL16UTF16,_.AL16UTF16、に環境変数NLS_LANGを設定しようとしましたが、同じエラーが発生します。私はUTF-8のファイルを読み取り、Unicodeでエンコードされたテーブルへの書き込みをしようとしていることを考えると

、誰もがcx_OracleはまだASCIIに自分のデータを変換しようとしていることになる理由を考えることができますか?

私はこのコードを使用してエラーを生成することができるよ:

field_map = { 
    ... 
} 

with open('all.csv', encoding='utf8') as f: 
    reader = csv.DictReader(f) 
    out_rows = [] 

    for row in reader: 
     if i == 1000: 
      break 

     out_row = {} 
     for field, source_field in field_map.items(): 
      out_val = row[source_field]    
      out_row[field] = out_val 

     out_rows.append(out_row) 

     i += 1 

out_db = datum.connect('oracle-stgeom://user:[email protected]') 
out_table = out_db['service_requests'] 
out_table.write(out_rows, chunk_size=10000) 

datumモジュールは、私が働いているデータ抽象化ライブラリです。 Oracle表への書き込みを行う関数は、hereです。

フルトレースバックは、次のとおりです。

File "C:\Projects\311\write.py", line 64, in <module> 
    out_table.write(out_rows, chunk_size=10000) 
    File "z:\datum\datum\table.py", line 89, in write 
    self._child.write(rows, from_srid=from_srid, chunk_size=chunk_size) 
    File "z:\datum\datum\oracle_stgeom\table.py", line 476, in write 
    self._c.executemany(None, val_rows) 
UnicodeEncodeError: 'ascii' codec can't encode character '\xa0' in position 1361: ordinal not in range(128) 
+0

完全なトレースバックを提供できますか?少なくとも、あなたが使用しているコードの関連部分は? cx_OracleはUnicodeテキストをデータベースに完全に書くことができます! –

+0

@AnthonyTuiningaいくつかのコードとトレースバックを追加しました。ありがとうございます! – Rob

答えて

1

は「エンコード」の値をチェックし、「nencodingは、」接続の属性。この値は、環境変数NLS_LANGおよびNLS_NCHARをチェックするOCIルーチンをコールすることによって設定されます。この値はUS-ASCIIまたはそれと同等のものです。データベースに書き込むとき、cx_Oracleはテキストを取り、Oracleクライアントが予期しているエンコーディングでエンコーディングしてバイト文字列を取得します。これはデータベースエンコーディングとは無関係であることに注意してください。一般に、最高のパフォーマンスを得るには、データベースとクライアントのエンコーディングを一致させることをお勧めしますが、そうしないと、Oracleは両方の文字セットで表現できるという条件で、 !

NLS_LANGの値が無効な場合は、基本的に無視されます。 AL16UTF16はそのような無効なエントリの1つです!だから、あなたが望む値(例えば、.UTF8)に設定し、あなたが望むものを得るまで接続上のエンコーディングとnencodingの値をチェックしてください。

あなたがそうしないと、cx_Oracleを介してデータベースにバインドされたすべての文字列は、NCHARエンコーディングではなく通常のエンコーディングであるとみなされます。これを無効にするには、cursor.setinputsizes()を使用し、入力タイプがNCHAR、FIXED_NCHARまたはLONG​​_NCHARであることを指定します。

関連する問題