python3.6にてcgiを作製しております。
クライアント(javascript)からデータを受け取った後までは、日本語がそのまま表示されるのですが、json.loads()にてjsonを読み込ませたところから文字コードが文字化けしてしまいます。
utf-8やshift-jisへの変換を試してみましたがすべて、変換できないといったエラーが返されてしまいます。
どうしても、方法がわからなくて困ってます。
ご教授いただければ幸いです。
※ 下記にソースを簡単に再現しました。
#クライアント
html
1<html lang="ja"> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 4 </head> 5 <body> 6 <form accept-charset="utf-8"> 7 : 8 :
javascript
1$.post("test.py", JSON.stringify({text:"ふぇふぇふぇ"}), (res) => { 2 : 3 : 4});
#サーバー(cgi)
python3
1#!/usr/bin/env python3.6 2# -*- coding: utf-8 -*- 3import json 4import cgi 5import cgitb 6import sys, io 7cgitb.enable() 8 9print('Content-type: text/html; charset=UTF-8\r\n') 10 11#sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') 12data = sys.stdin.read() 13print(data) 14params = json.loads(data) 15print(params) 16 17exit()
#出力結果
下記のようにdataまでは日本語ですが、json.loads後がバイトコードが表示されてしまいます。
output
1{"text":"ふぇふぇふぇ"} 2{'text':'\udce3\udc81\udcb5\udce3\udc81\udc87\udce3\udc81\udcb5\udce3\udc81\udc87\udce3\udc81\udcb5\udce3\udc81\udc87'}
#試したこと
下記一文を入れてutf-8に変換しようとしたら、unicodeEncodeErrorが返されました。
python3
1sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
error
1UnicodeEncodeError: 'utf-8' codec can't encode characters in position 9-26: surrogates not allowed 2 args =('utf-8', '{"text":"\udce3\udc81\udcb5\udce3\udc81\udc87\udce3\udc81\udcb5\udce3\udc81\udc87\udce3\udc81\udcb5\udce3\udc81\udc87"}', 9, 27, 'surrogates not allowed') 3 encoding ='utf-8' 4 end =27 5 object ='{"text":"\udce3\udc81\udcb5\udce3\udc81\udc87\udce3\udc81\udcb5\udce3\udc81\udc87\udce3\udc81\udcb5\udce3\udc81\udc87"}' 6 reason ='surrogates not allowed' 7 start =9 8 with_traceback =<built-in method with_traceback of UnicodeEncodeError object>
#補足20190424 13:21
環境面の補足です。
python3のデフォルトのencodingですが、環境で実行した場合とcgiから実行した場合で値がことなりました。サーバーでインタプリタで実行した際は「UTF-8」でしたが、
cgiから実行した場合は、stdin/stdoutともに、「ANSI_X3.4-1968」でした。
Bash
1$ locale 2LANG=ja_JP.UTF-8 3LC_CTYPE="ja_JP.UTF-8" 4LC_NUMERIC="ja_JP.UTF-8" 5LC_TIME="ja_JP.UTF-8" 6LC_COLLATE="ja_JP.UTF-8" 7LC_MONETARY="ja_JP.UTF-8" 8LC_MESSAGES="ja_JP.UTF-8" 9LC_PAPER="ja_JP.UTF-8" 10LC_NAME="ja_JP.UTF-8" 11LC_ADDRESS="ja_JP.UTF-8" 12LC_TELEPHONE="ja_JP.UTF-8" 13LC_MEASUREMENT="ja_JP.UTF-8" 14LC_IDENTIFICATION="ja_JP.UTF-8" 15LC_ALL=
#補足20190424 13:54
皆様のおかげでjsonファイルにunicodeを出力するところまで行けました。
unicodeであれば読み込むときに変換ができるので、なんとか行けそうです。
ただ、ファイルにコードではなくちゃんと日本語で表記されるようにするにはどうすればよいでしょうか?
dumpsでensure_ascii=Falseにしても、どうしてもunicodeで出力されてしまいます。
python3
1#!/usr/bin/env python3.6 2# -*- coding: utf-8 -*- 3import json 4import cgi 5import cgitb 6import sys, io 7cgitb.enable() 8 9sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8') 10sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') 11sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') 12 13print('Content-type: text/html; charset=UTF-8\r\n') 14 15data = sys.stdin.buffer.read() 16print(data) 17params = json.loads(data) 18print(params) 19with open("sample", mode="w", encode="utf-8") as f: 20 json.dumps(params, f, indent=2, ensure_ascii=False) 21 22exit()
output
1{"text": "\u3042"} 2{"text": "あ"}
ファイルに{"text": "あ"}と出力したい。
sample
1{"text": "\u3042"}
#補足20190424 14:11
解決しました。
ソースを何度も修正する際にミスが有ったようです。
具体的には、同じコードを複数書いてexit()で実行されないようにしていたのですが、
ensure_ascii=Falseを追加する場所を間違えてました。
ずっとこの課題に取り組み、疲れが溜まっていたのが原因です。
本当に解決してよかったです。しばらく休みます。
下に最終的にうまく行ったコードを載せます。
python3
1#!/usr/bin/env python3.6 2# -*- coding: utf-8 -*- 3import json 4import cgi 5import cgitb 6import sys, io 7cgitb.enable() 8 9sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8') 10sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') 11sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') 12 13print('Content-type: text/html; charset=UTF-8\r\n') 14 15data = sys.stdin.buffer.read() 16print(data) 17params = json.loads(data.decode()) 18print(params) 19with open("sample", mode="w", encoding="utf-8") as f: 20 json.dumps(params, f, indent=2, ensure_ascii=False) 21 22exit()
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/04/24 02:51 編集