質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

3271閲覧

PythonでCSVファイルの入力をもとにJSONファイルの文字置換を行った際にエラーが出る

AudioStakes

総合スコア41

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2015/12/02 10:04

編集2015/12/02 11:34

PythonでCSVファイルの入力をもとにJSONファイルの文字置換を行った際に以下のようなエラーが生じます
どのようにすれば解決できるでしょうか?

Traceback (most recent call last): File "replace_text.py", line 28, in <module> for row in spamreader: File "replace_text.py", line 18, in unicode_csv_reader for row in csv_reader: File "replace_text.py", line 24, in utf_8_encoder yield line.encode('utf-8') UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)

行っていることは
①JSON(TopoJSON)ファイルの中からCSVファイルの1列目と同じ文字列を見つける(札幌市、など)
②見つけた文字列をCSVファイルの2列目の文字列に置換する(札幌市の場合は、id011002)
③全ての文字列を置換し終えたJSON(TopoJSON)ファイルを出力
ということです

使用しているpythonのプログラムは以下になります。

#coding:utf-8 ''' Created on 2014/03/27 @author: hitsuji ''' import csv # 置換リストをCSVファイルで読み込む words_filename = 'replace_words' document_in = 'yokohama.topojson' document_out = 'yokohama_topo_out.json' words = [] def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs): # csv.py doesn't do Unicode; encode temporarily as UTF-8: csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),dialect=dialect, **kwargs) for row in csv_reader: # decode UTF-8 back to Unicode, cell by cell: yield [unicode(cell, 'utf-8') for cell in row] def utf_8_encoder(unicode_csv_data): for line in unicode_csv_data: yield line.encode('utf-8') with open(words_filename + '.csv', 'rU') as csvfile: spamreader = unicode_csv_reader(csvfile, dialect=csv.excel) for row in spamreader: words.append(row) text = u"" with open(document_in, 'rU') as docfile: tmpdoc = docfile.read() docfile.close() text = tmpdoc.encode('utf-8') for pair in words: text = text.replace(pair[0], pair[1]) with open(document_out, 'w') as f: f.write(text) f.close()

それぞれのファイルの中身は以下のようになっています。

☆JSON(TopoJSON)ファイルの中身 (軽く1万文字は超えますが、省略します)

{"type":"Topology","objects":{"hokkaido":{"type":"GeometryCollection","crs":{"type":"name","properties":{"name":"urn:ogc:def:crs:EPSG::4612"}},"geometries":[ {"type":"Polygon","properties":{"name":"札幌市"},"arcs":[[0,1,2,3,4,5]]}, {"type":"Polygon","properties":{"name":"旭川市"},"arcs":[[6,-6,7,8,9,10]]}, {"type":"Polygon","properties":{"name":"小樽市"},"arcs":[[11,-1,-7,12,13]]}, {"type":"Polygon","properties":{"name":"函館市"},"arcs":[[14,15,16,-2,-12,17]]}・・・

☆CSVファイルの中身 (200ほどこのような列が続きます)

1列目 2列目 札幌市 id011002 函館市 id012025 小樽市 id012033 旭川市 id012041 ・ ・ ・

どなたかこの解決方法をご存知の方がおりましたら、アドバイスをお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiro-k

2015/12/02 10:14

日本語を正しく処理できていないためにエラーが出ていると想定されます。 プログラムのどの部分が「日本語の扱い」として問題なのかは、プログラムを見てみないとなんとも言えません。 差し支えない範囲で、エラーが出ている周辺のプログラムを開示していただけないでしょうか?
hiro-k

2015/12/02 10:52 編集

jsonファイル, csvファイルの文字コードはそれぞれ何なのでしょうか?
AudioStakes

2015/12/02 11:26

ご指摘ありがとうございます! json, csvファイルのどちらもutf-8となっております
guest

回答2

0

ベストアンサー

python での日本語の扱いは下記が参考になるかと思います。
http://qiita.com/yubessy/items/9e13af05a295bbb59c25

エラーになっている部分は、そのページの下の方の表の、
'あいう' を .encode('utf-8') して エラー(1) になっている状態と考えられると思われます。
つまり、 for line in unicode_csv_data: で読み込まれた line は strオブジェクトになっていて、
これをline.decode('utf-8') とすれば、lineをutf-8形式の文字列として解釈して
unicodeオブジェクトになります。

text = tmpdoc.encode('utf-8') の行も同様の問題が有ると考えられます。

一方、f.write(text) はそのままだと unicodeオブジェクトを書き出すことになるため、
utf-8で書き出すためには、 f.write(text.encode('utf-8'))とする必要があるかと思います。

投稿2015/12/02 12:16

編集2015/12/02 12:17
hiro-k

総合スコア902

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AudioStakes

2015/12/02 12:31

詳細に解説していただき、ありがとうございます! 私の理解が間違っているかもしれませんが 指摘してくださった3点について以下のように変えて実行しました。 yield line.decode('utf-8') text = tmpdoc.decode('utf-8') f.write(text.encode('utf-8')) その結果、以下の様な同様のエラーが生じております。 File "replace_text.py", line 28, in <module> for row in spamreader: File "replace_text.py", line 18, in unicode_csv_reader for row in csv_reader: UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128) 何が間違っているのでしょう・・・。
hiro-k

2015/12/02 14:36

一つ確認させてください。 python は2.x系ですか?それとも3.x系ですか?
hiro-k

2015/12/02 15:33

http://docs.python.jp/2/library/csv.html に参考にされたと思われるコードが有りました。 yield line.encode('utf-8') は unicode をサポートしてない csv モジュールに漢字を通すために utf-8にしている部分ですね。で、入力ファイルが utf-8ということで、この部分は、何もしない yeild line にするのか Lhankor_Mhy さんのアドバイスを受けた変更の通りにするのが正しいようです。で、その結果出てくる、 Traceback (most recent call last): File "replace_text.py", line 36, in <module> text = tmpdoc.encode('utf-8') UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 200: ordinal not in range(128) については、 text = tmpdoc.decode('utf-8') とすることでエラーが出なくなります。
AudioStakes

2015/12/02 22:43

hiro-kさんのおかげで、解決することができました!ありがとうございます! pythonは2.7を使っております。 ご指摘いただいた通り、 yeild line text = tmpdoc.decode('utf-8') に変更したところ、目的通りの結果を得ることができました。 詳しく説明していただき、ありがとうございました。
AudioStakes

2015/12/02 23:00

追記 最後の出力のところで、 f.write(text.encode('utf-8')) としなければエラーが出てしまうこともあるようです。
hiro-k

2015/12/02 23:05

置き換えの結果、全ての日本語が無くなって id のみになるのであれば、 f.write(text) で問題なく、一部置き換えられずに日本語が残る場合には、 f.write(text.encode('utf-8')) にする必要が有るのだと思います。 日本語が全くない状態で、 f.write(text.encode('utf-8')) としても副作用は有りませんので、「日本語が残る可能性が全く無い」ということでないのであれば、 f.write(text.encode('utf-8')) にしておくのが良いと思います。
AudioStakes

2015/12/03 04:55

とてもわかりやすい説明をありがとうございます。 出力結果を確認したところ、たしかに日本語が残った場合のみ f.write(text.encode('utf-8')) にする必要が有りました。
guest

0

lineunicodeではなくstrだと思いますので、unicodeに戻してからエンコードするか、CSVファイルの文字コード次第ではエンコードせずにそのまま突っ込むかすればいいのではないかと思います。

投稿2015/12/02 11:29

編集2015/12/02 11:30
Lhankor_Mhy

総合スコア36115

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2015/12/02 11:37

補足拝読。それではエンコードせずにそのまま突っ込めば動くのでは。
AudioStakes

2015/12/02 12:19

エンコードしないでそのまま突っ込む、とはどのようにすれば良いのでしょう? とりあえず、 def utf_8_encoderをなくし、 csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),dialect=dialect, **kwargs)を csv_reader = csv.reader(csvfile,dialect=dialect, **kwargs)に変えて動かしてみたところ、 Traceback (most recent call last): File "replace_text.py", line 36, in <module> text = tmpdoc.encode('utf-8') UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 200: ordinal not in range(128) というエラーが出ています。 おそらく私のコードが、「そのまま突っ込む」ことができていないのだと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問