3

重複の可能性:
Unicode を UTF-8 Python に変換する

私は非常に新しい Python プログラマーで、最初のスクリプトに取り組んでいます。スクリプトは、plist 文字列からテキストを取得し、それに何らかの処理を行ってから、HTML メールとしてパッケージ化します。

エントリのいくつかから、恐ろしい Unicode の "outside ordinal 128" エラーが表示されます。

エンコードとデコードについてできる限り読んだので、エンコードを取得することが重要であることはわかっていますが、いつ、どのようにこれを行うかを正確に理解するのに苦労しています.

問題のある変数は、最初に plistlib を使用して取り込まれ、次のようにマークダウンから HTML に変換されます。

entry = result['Entry Text']
donotecontent = markdown2.markdown(entry)

後で、次のようにメールに入れられます。

html = donotecontent + '<br /><br />' + var3
part1 = MIMEText(html, 'html')
msg.attach(part1)

私の質問は、このコンテンツの Unicode 文字が原因でエラーがスローされないようにするための最善の方法は何かということです。私は文字を無視しないことを好みます。

4

3 に答える 3

11

壊れた英語でごめんなさい。私は中国語/日本語を話し、毎日 CJK 文字を使用しています。encode()Ceron はこの問題のほとんどを解決したので、 /の使用方法についてはdecode()再度説明しません。

Unicode オブジェクトをキャストするために使用str()すると、Unicode 文字列がバイトデータにエンコードされます。unicode()オブジェクトをキャストするために使用するstrと、バイトデータがユニコード文字にデコードされます。

また、エンコーディングは から返されたものでなければなりませんsys.getdefaultencoding()

デフォルトでは、デフォルトで「ascii」を返します。/キャストsys.getdefaultencoding()を実行すると、エンコード/デコード例外がスローされる場合があります。str()unicode()

str()またはによる str <-> Unicode 変換unicode()、および 'utf-8' による暗黙的なエンコード/デコードを行いたい場合は、次のステートメントを実行できます。

import sys    # sys.setdefaultencoding is cancelled by site.py
reload(sys)    # to re-enable sys.setdefaultencoding()
sys.setdefaultencoding('utf-8')

また、 utf-8 でエンコードされた basestring オブジェクトを後で実行しstr()て変換します。unicode()

ただし、encode()/をdecode()明示的に使用することをお勧めします。コードのメンテナンスが容易になるからです。

于 2012-11-21T04:40:01.973 に答える
4

strPython 2.x を使用していると仮定すると、文字列には と の 2 種類があることを思い出してくださいunicodestrはバイト文字列unicodeですが、Unicode 文字列です。unicode文字列は任意の言語でテキストを表すために使用できますが、テキストをコンピューターに保存したり、電子メールで送信したりするには、そのテキストをバイトで表す必要があります。バイトを使用してテキストを表現するには、コーディング形式が必要です。多くのコーディング形式があり、Python はデフォルトでasciiを使用しますが、 asciiはほとんどが英字の少数の文字しか表現できません。asciiを使用してテキストを他の文字でエンコードしようとすると、有名な "outside ordinal 128" が得られます。例えば:

>>> u'Cerón'.encode('ascii')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 3:
 ordinal not in range(128)

str(u'Cerón')Python はデフォルトでasciiunicodeを使用して に変換するため、を使用する場合も同じことが起こりますstr

これを機能させるには、別のコーディング形式を使用する必要があります。UTF-8は、任意の Unicode テキストをバイトとして表現できるコーディング形式です。u'Cerón'ユニコード文字列をバイトに変換するには、次を使用する必要があります。

>>> u'Cerón'.encode('utf-8')
'Cer\xc3\xb3n'

今回はエラーなし。

さて、メールの問題に戻りましょう。MIMETextすでにエンコードされた引数を受け入れるを使用していることがわかります。strあなたの場合はhtml変数です。MIMEText使用されているエンコーディングの種類を指定する引数も受け入れます。したがって、あなたの場合、htmlが Unicode 文字列の場合は、それをエンコードしてutf-8charset パラメータも渡す必要があります (HTMLTextデフォルトで ascii を使用するため):

part1 = MIMEText(html.encode('utf-8'), 'html', 'utf-8')

htmlただし、が既に のstr代わりに でunicodeある場合、エンコーディングは失敗するため、注意してください。これは Python 2.x の問題の 1 つで、既にエンコードされた文字列をエンコードできますが、エラーがスローされます。

リストに追加するもう 1 つの問題は、utf-8がascii文字と互換性があり、Python は常にasciiを使用して文字列を自動的にエンコード/デコードしようとすることです。文字列を適切にエンコードしていなくても、ASCII文字のみを使用している場合、問題なく動作します。ただし、何らかの理由でASCII以外の文字がメッセージに含まれていると、エラーが発生し、エラーの検出が難しくなります.

于 2012-11-21T03:45:21.557 に答える
0

覚えておいてください: Unicode をデコードすることはできず、str をエンコードすることもできません

>>> u"\xa0".decode("ascii", "ignore")

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    u"\xa0".decode("ascii", "ignore")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 0: ordinal not in range(128)


>>> "\xc2".encode("ascii", "ignore")

Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    "\xc2".encode("ascii", "ignore")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)

この優れたチュートリアルをチェックしてください

于 2012-11-21T03:12:10.480 に答える