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

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

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

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

Q&A

3回答

4474閲覧

[Python] byte型の変数の中にあるバックスラッシュを2つから1つへ置換したい

m.shinha

総合スコア4

Python

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

0グッド

0クリップ

投稿2020/02/28 04:14

前提・実現したいこと

サーバー(Python)とクライアント(ブラウザ、Javascript)の間でWebSocketを通じた双方向の文字列交換をするプログラムを現在作っています。
サーバー側で、クライアント側から投げられた日本語を含む文字列をそのまま解釈しようとすると文字化けを起こしてしまうので、いろいろ調査した結果

Python

1x = '{"comment":"琴葉・・・","command":"test","ch":1}' #クライアント側から受け取った文字化けした文字列 2x = x.encode('unicode-escape') # b'{"comment":"\xe7\x90\xb4\(以下略) という結果になる 3x = x.decode('utf-8') 4print (x) 5#期待する出力は {"comment":"琴葉・・・","command":"test","ch":1} 6#実際の出力は {"comment":"\xe7\x90\xb4(以下略)

というようにunicode-escapeの形に直してやってから、それをutf-8として解釈させることで文字化けを解消する方法を思いつきました。
しかし2行目のencode()を行うと頭にバックスラッシュが2つ入り、3行目のdecode()で正しく変換されません。byte型の時点で b'\xe7\x90\xb4' のように、バックスラッシュが1つだけであれば正しくdecode()ができることを確認できたので、そこで2行目のencodeの直後に''を''に置換させる処理を置こうと試しているのですがどうもうまくいかないのです。

発生している問題

File "n.py", line 2 x = x.replace(b'\',b'\') ^ SyntaxError: EOL while scanning string literal

調べてみるとなぜ raw 文字列 (r-strings) はバックスラッシュで終わってはいけないのですか?という記述を見つけました。それによると

正確には、奇数個のバックスラッシュで終わってはいけません。終わりの対になっていないバックスラッシュは、閉じ引用文字をエスケープし、終っていない文字列を残してしまいます。

とのことでした。現在エラーが起きている箇所はbyte型で、この問題に関係あるのかないのかは正直自分でもわからないのですが、関係あるとしたら「閉じ引用文字をエスケープしてエラーが起きている」ということが今回の場合でもいえそうです。もしそうであった場合は置換に際して回避策、代替策などはあるのでしょうか?

該当のソースコード

python

1x = '{"comment":"琴葉・・・","command":"test","ch":1}'.encode('unicode-escape') 2x = x.replace(b'\',b'\') 3x = x.decode('utf-8') 4print (x)

補足情報(FW/ツールのバージョンなど)

検証環境:
・Python 3.7.4
・Windows 10 Home(64bit)

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

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

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

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

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

guest

回答3

0

https://docs.python.org/ja/3/library/stdtypes.html#bytes

リテラル以外に、幾つかの方法で bytes オブジェクトを作ることができます:
整数の iterable から: bytes(range(20))

python

1bytes(ord(c) for c in x).decode('utf-8')

とか

python

1bytes(map(ord, x)).decode('utf-8')

とか。

plain

1>>> x = '{"comment":"ç<90>´è<91><89>ã<83>»ã<83>»ã<83>»","command":"test","ch":1}' 2 3>>> print(bytes(ord(c) for c in x).decode('utf-8')) 4{"comment":"琴葉・・・","command":"test","ch":1} 5 6>>> print(bytes(map(ord, x)).decode('utf-8')) 7{"comment":"琴葉・・・","command":"test","ch":1}

こんなことをしなくていいようにするのが本筋だと思います。

投稿2020/02/28 07:01

編集2020/02/28 07:09
quickquip

総合スコア11038

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

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

0

こうするとどうなりますか?

python

1x = '{"comment":"琴葉・・・","command":"test","ch":1}' 2x = x.encode('ISO-8859-1') 3x = x.decode('utf-8') 4print (x)

投稿2020/02/28 05:11

Lhankor_Mhy

総合スコア36115

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

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

m.shinha

2020/02/28 11:58

encode('ISO-8859-1')としてやると正しく変換されました!
guest

0

まず、おそらく根本的にはクライアント側のjsonデータのつくり方に問題があると思われます。
jsonデータのcomment文字列は、元がUTF-8で表現されていた文字列を無理やりASCII`文字列に変換させたような感じになっています。
これはクライアント側の問題なので、それを直すのが本筋です。
が、とりあえずサーバ(受信)側で何とかするとしたら、以下のようなコードで復元できそうです。

Python

1import json 2import array 3 4# まずはcomment部分のみを抽出する 5x = '{"comment":"琴葉・・・","command":"test","ch":1}' 6x = json.loads(x) 7comment = x['comment'] 8print(comment) # 琴葉・・・ 9 10# comment文字列をASCIIコードの数値のリストとしてとらえ直す 11l = [ord(c) for c in comment] 12print(l) # [231, 144, 180, 232, 145, 137, 227, 131, 187, 227, 131, 187, 227, 131, 187] 13 14# 数値のリストをバイナリのストリームとしてとらえ直す 15b = array.array('B', l).tobytes() # 'B'=unsigned char 16 17# バイナリを'utf-8'としてデコード 18s = b.decode('utf-8') 19print(s) # 琴葉・・・

投稿2020/02/28 04:58

can110

総合スコア38266

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

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

m.shinha

2020/02/28 13:22

直す方法はあるけれどやっぱりクライアントが悪いということなんですね。サンプルコードも参考になりました、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問