Unicode —Werkzeugのドキュメント
Unicode
初期のPython2日以降、UnicodeはすべてのデフォルトのPythonビルドの一部でした。 これにより、開発者は非ASCII文字を簡単な方法で処理するアプリケーションを作成できます。 ただし、Unicodeを使用するには、特にそれをサポートしていないライブラリを使用する場合は、その問題に関する基本的な知識が必要です。
Werkzeugは、HTTP標準がユニコードに対応していない場合でも、テキストデータが想定されるすべての場所で内部的にユニコードを使用します。 基本的に、すべての受信データは指定された文字セットからデコードされるため(デフォルトでは utf-8 )、バイト文字列を操作する必要はありません。 次に、送信ユニコードデータがターゲット文字セットに再度エンコードされます。
PythonのUnicode
Python 2には、 str と unicode の2つの基本的な文字列型があります。 str はエンコードされたユニコードデータを運ぶことができますが、それは常にバイトで表されますが、 unicode タイプはバイトではなく文字を含みます。 これは何を意味するのでしょうか? あなたがドイツのウムラウトöを持っていると想像してください。 ASCIIではその文字を表現できませんが、 latin-1 および utf-8 文字セットでは表現できますが、エンコードすると外観が異なります。
>>> u'ö'.encode('latin1')
'\xf6'
>>> u'ö'.encode('utf-8')
'\xc3\xb6'
そのため、öはエンコーディングによってまったく異なるように見える場合があり、操作が困難になります。 解決策は、 unicode タイプを使用することです(上記で行ったように、文字列の前に u プレフィックスがあることに注意してください)。 Unicodeタイプは、öのバイトを格納しませんが、これがLATIN SMALL LETTER O WITH DIAERESIS
であるという情報を格納します。
len(u'ö')
を実行すると、常に期待される「1」が得られますが、len('ö')
は、'ö'
のエンコーディングによって異なる結果をもたらす可能性があります。
HTTPのUnicode
ユニコードの問題は、HTTPがユニコードが何であるかを知らないことです。 HTTPはバイトに制限されていますが、Werkzeugがすべての着信データと発信データを自動的にデコードおよびエンコードするため、これは大きな問題ではありません。 基本的に、これが意味するのは、ブラウザからWebアプリケーションに送信されるデータは、デフォルトでutf-8バイト文字列から unicode 文字列にデコードされるということです。 アプリケーションからブラウザに返送された、まだバイト文字列ではないデータは、utf-8にエンコードされて戻されます。
通常、これは「正常に機能」し、心配する必要はありませんが、この動作に問題がある場合があります。 たとえば、Python 2IOレイヤーはUnicodeに対応していません。 これは、ファイルシステムからのデータを操作するときはいつでも、それを適切にデコードする必要があることを意味します。 ファイルシステムからテキストファイルをロードする正しい方法は次のようになります。
f = file('/path/to/the_file.txt', 'r')
try:
text = f.decode('utf-8') # assuming the file is utf-8 encoded
finally:
f.close()
指定されたエンコーディングから自動的にデコードするオープン関数を提供するコーデックモジュールもあります。
エラー処理
内部エンコードまたはデコードを行う関数は、str.decode()
およびstr.encode()
に渡されるerrors
キーワード引数を受け入れます。 デフォルトは'replace'
であるため、エラーを簡単に見つけることができます。 エラーをキャッチしてクライアントに不良データを報告するには、'strict'
に設定すると便利な場合があります。
要求オブジェクトと応答オブジェクト
リクエストオブジェクトとレスポンスオブジェクトは通常、Werkzeugを利用したアプリケーションの中心的なエンティティであるため、これら2つのクラスをサブクラス化することで、Werkzeugが動作するデフォルトのエンコーディングを変更できます。 たとえば、アプリケーションをutf-7および厳密なエラー処理に簡単に設定できます。
from werkzeug.wrappers import BaseRequest, BaseResponse
class Request(BaseRequest):
charset = 'utf-7'
encoding_errors = 'strict'
class Response(BaseResponse):
charset = 'utf-7'
エラー処理はすべてのデコードに対してのみカスタマイズ可能であり、エンコードに対してはカスタマイズできないことに注意してください。 Werkzeugでエンコードエラーが発生すると、UnicodeEncodeError
が発生します。 ターゲット文字セットに存在しないデータを作成しないのはあなたの責任です(utf-8などのすべてのUnicodeエンコーディングでは問題ありません)。
ファイルシステム
バージョン0.11で変更されました。
バージョン0.11まで、WerkzeugはPythonのstdlib機能を使用してファイルシステムのエンコーディングを検出していました。 ただし、Werkzeugに対するいくつかのバグレポートでは、sys.getfilesystemencoding()
の値は従来のUNIXシステムでは信頼できないことが示されています。 通常の問題は、LANG
および同様の環境変数が設定されていないシステムの構成ミスが原因です。 このような場合、PythonはファイルシステムエンコーディングとしてデフォルトでASCIIになります。これは非常に保守的なデフォルトであり、通常は間違っており、回避するよりも多くの問題を引き起こします。
したがって、WerkzeugはファイルシステムエンコーディングをUTF-8
に強制し、BSDまたはLinuxで実行されていることを検出すると警告を発行し、sys.getfilesystemencoding()
はASCIIエンコーディングを返します。
werkzeug.filesystem も参照してください。