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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

29482閲覧

python3でのbytes型の中で.decode('utf-8')を指定してもエラーになる

Casablanca_mtg

総合スコア209

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2017/01/05 03:47

お世話になります。
python入門(2&3対応)で勉強しています
Python2系から3系になってから文字列はUnicodeになり、そしてbytes型が追加されたことはわかりました。
bytes型を実際に書籍通りで実行してみました

C:\Users\mtg-1>python
Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.

b'abc'

b'abc'

bytes('あいう','utf8')

b'\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86'

b'あい '+ 'うえお'

File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.

b'あい'.decode('utf-8') + 'うえお'

File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.

str(b'あいう')

File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.
*********************************

b'あい' + 'うえお'

File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.

これは理解できます。

b'あい'.decode('utf-8') + 'うえお'

File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.

str(b'あいう')

File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.

.decode('utf-8')で連結させようとしてもバイトにはASCIIリテラル文字しか含めることができません。

また同じ理由でStr関数に直接渡すことができない

import sys
print(sys.getdefaultencoding())

utf-8

print(sys.stdout.encoding)

cp932

print('こんにちはこんにちは')

こんにちはこんにちは

となります

print(sys.stdout.encoding)

cp932→utf-8にするにはどうすればいいのでしょうか?

よろしくお願いいたします

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

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

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

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

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

guest

回答3

0

ベストアンサー

python3では

  • b'~'にASCII文字以外を含めることはできません。
  • str→bytes はencode/bytes→strはencodeを使います。
C:\Windows\system32>python Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.stdin.encoding 'cp932' >>> sys.stdout.encoding 'cp932' >>> sys.getdefaultencoding() 'utf-8' >>> ai = 'あい' >>> type(ai) <class 'str'> # b'~'にASCII文字以外を含めることはできない。b'ab'などはOK。 >>> ai = b'あい' File "<stdin>", line 1 SyntaxError: bytes can only contain ASCII literal characters. # str型(=UNICODE文字列)からutf-8エンコード(表現)されたbytes型を得る。 >>> ai = 'あい' >>> ai_utf8 = ai.encode('utf-8') >>> ai_utf8 b'\xe3\x81\x82\xe3\x81\x84' >>> type(ai_utf8) <class 'bytes'> # str型(=UNICODE文字列)からcp932エンコード(表現)されたbytes型を得る。 >>> ai_sjis = ai.encode('cp932') >>> ai_sjis b'\x82\xa0\x82\xa2' >>> type(ai_sjis) <class 'bytes'> # utf-8エンコード(表現)されたbytes型からstr型(=UNICODE文字列)を得る(デコードする)。 # 引数なしだとbyte型のエンコード(表現)はdefaultencoding(=utf-8)とみなして処理される。 >>> ai_str = ai_utf8.decode() >>> ai_str 'あい' >>> type(ai_str) <class 'str'> # cp932エンコード(表現)されたbytes型からstr型(=UNICODE文字列)を得る(デコードする)。 # utf-8ではないのにutf-8とみなしてデコードしようとしてエラー >>> ai_str = ai_sjis.decode() Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 0: invalid start byte # 明示的にbyte型のエンコード(表現)を指定してデコードする。 >>> ai_str = ai_sjis.decode('cp932') >>> ai_str 'あい' >>> type(ai_str) <class 'str'>

以下、本筋とは離れた内容になるため、参考程度にお読みください。

シェル(ターミナル)とpythonの標準入力の文字コードが異なる場合

ちなみにWin10+Anacondaの対話環境でPYTHONIOENCODING環境変数を利用してみましたが
コマンドプロンプト上(cp932)とpython実行環境(utf-8)の文字コード不整合のためか、下記のようにエラーになりますね。

C:\Windows\system32>chcp 現在のコード ページ: 932 C:\Windows\system32>set PYTHONIOENCODING=utf-8 C:\Windows\system32>echo %PYTHONIOENCODING% utf-8 C:\Windows\system32>python Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.stdin.encoding 'utf-8' >>> sys.stdout.encoding 'utf-8' >>> ai = 'あい' File "<stdin>", line 0 ^ SyntaxError: 'utf-8' codec can't decode byte 0x82 in position 6: invalid start byte

コマンドプロンプトのコードページを65001(UTF-8)にしてみると…

C:\Windows\system32>set PYTYONIOENCODING=utf-8 C:\Windows\system32>echo %PYTHONIOENCODING% utf-8 C:\Windows\system32>chcp Active code page: 65001 C:\Windows\system32>python Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.stdin.encoding 'utf-8' >>> sys.stdout.encoding 'utf-8' >>> sys.getdefaultencoding() 'utf-8' >>> ai = 'ab' >>> ai 'ab' # ↓ IMEが立ち上がらないのでコピーペーストで入力 >>> ai = 'あい' # ↑ pytyon.exeが異常終了?してコマンドプロンプトに戻る… # 何らかのエラーメッセージを出力しているのかもしれないが文字コード不整合のため表示されていない? C:\Windows\system32>

投稿2017/01/05 07:00

編集2017/01/05 08:34
can110

総合スコア38262

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

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

ikedas

2017/01/05 07:41

あてずっぽですが、「chcp 65001」を実行してからやったらどうなるでしょうか。
can110

2017/01/05 08:22

理屈上はうまくいくはずなのですが、思わぬ結果にorz
Casablanca_mtg

2017/01/05 09:25

この件についてずいぶん悩んでいます。がしかし結果が得られていません。encodeでの内容は難しいと感じます。PCの環境でどうしても解決できない??秀和システムにも質問しました unicode('あいう') と'あいう'.decode() のエラー → これは、'あいう'のエンコードと、デフォルトのエンコードがあ っていないものと思われます。 unicode('あいう', 'utf-8') とunicode('あいう', 'euc_jp') のエラー → これは、'あいう'のエンコードがutf-8またはeuc_jpになってい ないものと思われます。 'あいう'のエンコードはソースコードの# -*- coding: utf-8 -*-や、 シェルの環境によって変わります。 次のようにして、'あいう'のエンコードを確認してみてください。 http://php6.jp/python/2011/01/13/encoding/ デフォルトのエンコードは import sys sys.getdefaultencoding() で知ることができます。 これは、site-packagesの中にあるsitecustomize.pyで指定されるこ とが多いです。 http://php6.jp/python/2011/01/13/encoding/これも読みました しかし解決に至らない状況です
can110

2017/01/05 10:01

回答にも追記しましたが、元の質問の内容とは離れていると思います。 まずはpython3環境内でのstr/bytesの相互変換についての理解を深め、その後に外部とのデータ入出力における文字コード変換を学習したほうがよいでしょう。 (たとえばUTF-8で書かれた文字列を読込んでShift-JISで書き出すなど) その場合も、標準入出力ではなく、ファイル入出力で行った方がよいです。
Casablanca_mtg

2017/01/05 10:13

すみません。同じ内容を秀和システムに確認した結果が上記でした。秀和システムが書いたものだったため年末に質問して回答をもらったのですがそれで実際試しましたができなかったため質問しました。(元の質問の内容とは離れていると思います。)→だから余計ややこしくなったのかもしれません。
Casablanca_mtg

2017/01/06 00:34

皆様ありがとうございます。2系と3系を書籍に従って切り替えながら勉強しています。 python3環境内でのstr/bytesの相互変換についての理解を深め、その後に外部とのデータ入出力における文字コード変換を学習したほう良いとのご意見真摯に受け止めさせていただいてこの章をじっくりやり直してみます。こうやって皆様のお力をお借りすることでいろいろ理解できるようになってきたことも確かです。さらに頑張ってみます。ありがとうございます
guest

0

(Windowsと合わない説明を修正しました)

コマンドプロンプトで端末の文字コードをUTF-8にするには、次のようにします。

> chcp 65001

Pythonの入出力の文字コードを変えるには、Pythonを起動する前にPYTHONIOENCODING環境変数を設定します。

> PYTHONIOENCODING=utf-8 > python ... ...

ちなみに、上記の方法だと標準入出力の全部 (sys.stdin.encodingsys.stdout.encodingsys.stderr.encoding) が変わります。どれか一つだけ (たとえばsys.stdout.encodingだけ) 変える場合は、

python

1import codecs 2import sys 3 4# Python 2.x 5sys.stdout = codecs.getwriter("utf-8")(sys.stdout) 6print u'あい' # bytes型ではだめ 7 8# Python 3.x 9sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) 10print('あい')

(追記)

Python 3では、文字列に特定の文字コードが指定されることはありません。Python内部では、文字データはすべてユニコードで扱われます。

文字データを実際にファイルに保存したり通信回線で送ったりするときは、バイトデータに変換してやる必要があります。つまり、Pythonの外部では文字はバイト型のデータで表されます。文字とバイトの間の変換ルールを文字コードと言います。文字コードには「UTF-8」や「CP932」などのいろいろな種類があります。

sys.stdout.encodingを変えるということは、print()で文字を出力するときにどの文字コードのバイトデータにするかを変える、ということです。出力先の端末 (画面) で想定している文字コードと違えば、正しく表示されません。例えば、端末の文字コードがUTF-8のときにsys.stdout.encodingをCP932にすれば、表示されるものは文字化けします。

投稿2017/01/05 05:47

編集2017/01/05 08:07
ikedas

総合スコア4317

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

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

Casablanca_mtg

2017/01/05 06:28

試してみました。 C:\Users\mtg-1>python Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import codecs >>> import sys >>> sys.stdout = codecs.getwriter('utf-8')(sys.stdout.detach()) >>> print('あい') 縺ゅ> 文字化けをしてしまいます。これはデフォルトはUTF-8なのだがコマンドプロンプトのエンコードはcp932なのでバイトにはASCIIリテラル文字しか含めることができない?このように理解したのですが・・・・
ikedas

2017/01/05 08:08 編集

回答に説明を追記してみました。 (再修正) 混乱させてすみません。Windowsが前提になっていなかったので、説明を修正しました。
Casablanca_mtg

2017/01/05 08:18

>chcp 65001は前に試しましたがこれにすると日本語が打てなくなります >>>bytes('あいう', 'utf-8')を記述しようとすると>>>bytes('aiu', 'utf-8')としか表示できません そのため”Bash on Ubuntu on Windowsの最高の日本語ターミナル環境を整える”でも考えた方がよいのかと思いましたがどうも質問の域からずれる気がしてまだやっていません
guest

0

python

1b'あい'.decode('cp932')

で、どうですか?

投稿2017/01/05 04:54

takeshi

総合スコア264

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

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

Casablanca_mtg

2017/01/05 06:20

実行しました。 C:\Users\mtg-1>python Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> b'あい'.decode('cp932') + 'うえお' File "<stdin>", line 1 SyntaxError: bytes can only contain ASCII literal characters. となりました。やはりバイトにはASCIIリテラル文字しか含めることができないですね
takeshi

2017/01/05 06:38

すいません、結合時の自動変換でのエラーかと思ったら、そもそも b'あい' と書くことが認められていないんですね。 どういうケースで必要なのか分かりませんが通常は単に 'あい' と書くべきかと思います。 本当のバイト列からの変換(ファイルのバイナリでの読み書きなど)であれば、 b'\x82\xa0\x82\xa2'.decode('sjis') というようにしてあげれば unicode に変換できるようです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問