10

このコードをコンソールで実行すると (ロシア語で) うまく動作しますが、Apache2 サーバーで cgi のように実行すると失敗します: <type 'exceptions.UnicodeEncodeError'>: 'ascii' codec can't encode characters in position 8-9: ordinal not in range(128). コードは次のとおりです。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import cgitb
cgitb.enable()

print "Content-Type: text/html;charset=utf-8"
print 
s=u'Nikolja \u043d\u0435 \u0421\u0430\u0440\u043a\u043e\u0437\u0438!'
print s#.encode('utf-8')

はい、解決策はコメントを外すこと.encode('utf-8')ですが、理由を理解するのに時間がかかり、答えがわかりません。

4

2 に答える 2

11

コンソールから実行すると、Python はコンソールのエンコーディングを検出し、コンソールに出力された Unicode をそのエンコーディングに暗黙的に変換できます。そのエンコーディングが印刷しようとしている文字をサポートしていない場合でも、失敗する可能性があります。UTF-8 はすべての Unicode 文字をサポートできますが、米国 Windows の cp437 などの他の一般的なコンソール エンコーディングはサポートしていません。

stdout がコンソールでない場合、Python 2.X は、コンソールのエンコーディングを判別できない場合、デフォルトで ASCII を使用します。そのため、Web サーバーでは明示的に出力を自分でエンコードする必要があります。

例として、コンソールと Web サーバーから次のスクリプトを試してください。

import sys
print sys.stdout.encoding

コンソールからはエンコードを取得する必要がありますが、Web サーバーからはNone. Python 2.X は使用しますasciiが、Python 3.X はutf-8エンコーディングを決定できない場合に使用することに注意してください。

この問題は、出力をリダイレクトするときにコンソールでも発生する可能性があります。このスクリプト:

import sys
print >>sys.stderr,sys.stdout.encoding
print >>sys.stderr,sys.stderr.encoding

直接実行した場合とリダイレクトした場合は、次のように返されますstdout

C:\>test
cp437
cp437

C:\>test >out.txt
None
cp437

stderrリダイレクトされていないため、メモは影響を受けませんでした。

環境変数PYTHONIOENCODINGを使用して、デフォルトの stdout/stdin エンコーディングをオーバーライドすることもできます。

于 2012-08-01T21:09:40.300 に答える
5

Try applying the utf-8 codecs on stdin and stdout...

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import cgitb
import sys
import codecs

sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
# If you need input too, read from char_stream as you would sys.stdin
char_stream = codecs.getreader('utf-8')(sys.stdin)

cgitb.enable()

print "Content-Type: text/html;charset=utf-8"
print 
s=u'Nikolja \u043d\u0435 \u0421\u0430\u0440\u043a\u043e\u0437\u0438!'
print s
于 2012-08-01T17:48:25.410 に答える