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

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

ただいまの
回答率

90.60%

  • Python 3.x

    5894questions

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

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

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 11K+

kasaburanka

score 123

お世話になります。
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にするにはどうすればいいのでしょうか?

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

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 16:41

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

    キャンセル

  • 2017/01/05 17:22

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

    キャンセル

  • 2017/01/05 18: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/これも読みました
    しかし解決に至らない状況です

    キャンセル

  • 2017/01/05 19:01

    回答にも追記しましたが、元の質問の内容とは離れていると思います。

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

    キャンセル

  • 2017/01/05 19:13

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

    キャンセル

  • 2017/01/06 09:34

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

    キャンセル

0

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


で、どうですか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/05 15: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リテラル文字しか含めることができないですね

    キャンセル

  • 2017/01/05 15:38

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

    キャンセル

0

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

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

> chcp 65001


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

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


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

import codecs
import sys

# Python 2.x
sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
print u'あい' # bytes型ではだめ

# Python 3.x
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
print('あい')

(追記)

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/05 15: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リテラル文字しか含めることができない?このように理解したのですが・・・・

    キャンセル

  • 2017/01/05 16:43 編集

    回答に説明を追記してみました。

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

    キャンセル

  • 2017/01/05 17:18

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

    キャンセル

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

  • ただいまの回答率 90.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    5894questions

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