5

argparsePythonコードの引数を読み込むために使用しています。titleこれらの入力の 1 つは、Unicode 文字を含むことができるファイル [ ] のタイトルです。22少女時代22テストストリングとして使用しています。

入力の値をtitleファイルに書き込む必要がありますが、文字列を変換しようとすると、UTF-8常にエラーがスローされます。

UnicodeDecodeError: 'ascii' コーデックは位置 2 のバイト 0x8f をデコードできません: 序数が範囲外です (128)

私は周りを見回しており、文字列をu"foo"呼び出すための形式にする必要があることがわかり.encode()ました。

type()からの入力を実行すると、次のようargparseに表示されます。

<type 'str'>

私は次のような応答を得たいと思っています:

<type 'unicode'>

どうすれば正しい形で取得できますか?

考え:

を受け取るように変更argparseしますがstr、Unicode 文字列として保存しますu"foo"

parser.add_argument(u'title', metavar='T', type=unicode, help='this will be unicode encoded.')

このアプローチはまったく機能していません。考え?

編集1:

いくつかのサンプルコードtitle22少女時代22次のとおりです。

inputs = vars(parser.parse_args())
title = inputs["title"]
print type(title)
print type(u'foo')
title = title.encode('utf8') # This line throws the error
print title
4

3 に答える 3

12

入力データはSJIS エンコーディング(日本語の従来のエンコーディング) のようで、バイト文字列の位置 2 にバイト 0x8f が生成されます。

>>> '22少女時代22'.encode('sjis')
b'22\x8f\xad\x8f\x97\x8e\x9e\x91\xe322'

(Python 3 プロンプトで)

今、私はそれを推測している「文字列をUTF-8に変換する」には、次のようなものを使用しました

title.encode('utf8')

問題は、title実際には SJIS でエンコードされた文字列を含むバイト文字列であることです。Python 2 の設計上の欠陥により、バイト文字列を直接 d に変換でき、encodeバイト文字列が ASCII エンコードされていると見なされます。したがって、あなたが持っているものは概念的に同等です

title.decode('ascii').encode('utf8')

もちろん、decode呼び出しは失敗します。

代わりに、UTF-8 にエンコードする前に、SJIS から Unicode 文字列に明示的にデコードする必要があります。

title.decode('sjis').encode('utf8')

Mark Tolonen が指摘したように、おそらくコンソールに文字を入力していて、コンソールのエンコーディングが非 Unicode エンコーディングです。

これsys.stdin.encodingcp932Microsoft の SJIS の変種です。これには、

title.decode('cp932').encode('utf8')

コンソールのエンコードを標準の UTF-8 に設定する必要がありますが、Windows でそれが可能かどうかはわかりません。その場合は、デコード/エンコードの手順をスキップして、入力バイト文字列をファイルに書き込むだけでかまいません。

于 2012-10-06T23:04:53.460 に答える
4

設定は、Python 2.Xでのデコードのデフォルトをtype=unicode使用するようなものです。コンソールから実行する場合、入力に使用されるエンコーディングは次のようになります。unicode(arg)asciisys.stdin.encoding

inputs = vars(parser.parse_args())
title = inputs["title"]
print type(title)
print type(u'foo')
title = title.decode(sys.stdin.encoding)
print title

Windows のエンコーディングに関係なく機能するのはmbcsエンコーディングです。これは、非 Unicode Windows プログラムで使用されている現在のエンコーディングを表します。私はWindows エンコーディングと常に同じではないOEMargparseコンソール エンコーディングであるため、それが使用されているようです。米国の Windows では、はコンソールの OEM エンコーディングであり、 は Windows のエンコーディングです。sys.stdin.encodingcp437cp1252

import argparse
import codecs
parser = argparse.ArgumentParser()
parser.add_argument(u'title', metavar='T', type=str, help='this will be unicode encoded.')
opts = parser.parse_args()
title = opts.title.decode('mbcs')
with codecs.open('out.txt','w',encoding='utf-8-sig') as f:
    f.write(title)

out.txt元の入力がメモ帳に表示されるはずです。

エンコーディングは、utf-8-sigWindows が好む、いわゆるバイト オーダー マーク (BOM) を UTF-8 ファイルの先頭に書き込みます。 utf-8それが望ましくない場合は使用できますが、メモ帳はそれを好みます。

于 2012-10-06T23:17:44.313 に答える
3

だから、これは実際に私のために働く:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument(u'title', metavar='T', type=str, help='this will be unicode encoded.')
opts = parser.parse_args()
print opts.title.decode('utf8')

私の端末エミュレータ (OS X Terminal.app) は UTF-8 を使用しています。端末が UTF-8 操作用に構成されていない場合、機能しません (そして、Python の問題ではなく、端末の問題です)。

于 2012-10-06T23:01:21.343 に答える