もう一度、Windowsで
SamIzdatの独自のスクリプトインフォーマーを
実行し、コンソール
で「神秘的なシンボル」を見たとき
、私は自分自身に言いました。
このことと、Win32のDjango-vskyのようなログの出力をHabra-katの下で色付けする方法を説明します
(以下で説明するもの
はすべてPython 2.xブランチに適用されます
)最初のタスク。 コンソールへの正しいテキスト出力
症状
初期化されたI / Oシステムに「修正」を行い、Unicode行で
printステートメントのみを使用するまで、OSに関係なく、すべてがほぼ正常に動作します。
「奇跡」はさらに始まります-エンコーディングを変更するか(もう少し詳しく見てください)、またはロギングモジュールを使用して画面に表示します。 Linuxで期待される動作を設定しているようで、Windowsではutf-8で「ガベージ」が発生します。 あなたはWinの下で編集を開始します-1251はコンソールでクロールします...
理論的な遠足
いくつかのパラメーターは、文字を変換してコンソールに表示するためのパラメーターを担当します。
sys
モジュールのデフォルトのエンコーディングはsys.getdefaultencoding()
- 現在のロケールの優先エンコードは
locale.getpreferredencoding()
- 標準ストリーム
sys.stdout, sys.stderr
エンコード - ファイル自体のエンコードは混乱を招きますが、すべてが統一されており、utf-8のすべてのファイルに正しいヘッダーが含まれていることに同意します
- 「ボーナス」は、正しく設定されたエンコードを使用しても、Unicode行を印刷するときに文字が必要ない場合に、例外をスローする標準スレッドの愛です。
私たちは解決策を探しています
明らかに、これらすべての問題を取り除くには、何らかの形でそれらを均一にする必要があります。
そして、ここから楽しみが始まります。
うん! 「システム」は一般にASCIIで生きていることがわかります。 その結果、単純に入力/出力を処理しようとすると、「お気に入り」の例外
UnicodeEncodeError/UnicodeDecodeError
終了します。
さらに、例からわかるように、Linuxのどこにでもutf-8がある場合、Windowsには2つの異なるエンコーディングがあります。いわゆるANSI、cp1251で、グラフィックパーツとOEMに使用され、cp866にテキストを出力します。コンソール OEMエンコードはDOSからやって来ており、理論的には特別なチームによって再構成することもできますが、実際には長い間誰もこれを行っていません。
最近まで、私はこの迷惑を修正するために一般的な方法を使用しました:
そして、それは一般に、うまくいきました。
print
を使用していればうまくいきました。
logging
を通じて画面出力に行ったとき
logging
すべてが壊れました。
ええ、「it」はデフォルトのエンコーディングを使用するので、コンソールと同じエンコーディングを設定します。
sys.setdefaultencoding(sys.stdout.encoding or sys.stderr.encoding)
もう少し良くなりましたが:
- Win32では、テキストはkrakozyabryによって印刷され、明らかにcp1251を連想させます
- リダイレクトされた出力で開始すると、再び期待したものが得られません
- 定期的に、タイプ①(
①
)の文字をUnicodeに変換し、著者によって何らかの見出しに親切に追加されたテキストを印刷しようとすると、再びUnicodeEncodeError
がUnicodeEncodeError
ます!
最初の例をよく見てみると、対応するストリームの属性をチェックすることによってのみ望ましいcp866エンコーディングが得られることがわかります。 そして、常に利用できるとは限りません。
タスクの2番目の部分は、システムエンコーディングをutf-8のままにして、コンソールへの出力を正しく構成することです。
出力をカスタマイズするには、次のように出力ストリームの処理を再定義する必要があります。
import sys import codecs sys.stdout = codecs.getwriter('cp866')(sys.stdout,'replace')
このコードを使用すると、1石で2羽の鳥を殺すことができます。255文字のcp866で欠落しているすべての種類のウムラウトやその他のタイポグラフィを印刷するときに、目的のエンコードを設定し、例外から保護します。
このコードを普遍的にすることは残っています-任意の球状のコンピューターでOEMエンコードをどのように知ることができますか? pythonでANSI / OEMエンコーディングの既製のサポートをグーグルで検索することは合理的ではなかったため、WinAPIを少し思い出す必要がありました
UINT GetOEMCP(void);
...そしてそれをすべてまとめる:
2番目のタスク。 結論を色付けする
werkzeugと一緒にJangaのデバッグ出力を確認した後、私は自分に似たものが欲しかった。
グーグルは、
logging.StreamHandler
の最も単純な子孫から、インポート時に標準のStreamHandlerを自動的に置き換える特定のセットまで、さまざまな詳細度と利便性のプロジェクトを生成します。
それらのいくつかを試した後、
Stack Overflowのコメントの1つにリストされている単純なStreamHandlerの継承者を使用することになりましたが、これまでのところ非常に満足しています。
class ColoredHandler( logging.StreamHandler ): def emit( self, record ):
ただし、Windowsでは、このすべての作業はもちろん拒否されました。 そして以前に、Windowsシステムフォルダーの腸のどこかにsymfonyプロジェクトから「マジック」ansi.dllを追加することにより、コンソールでANSIコードのサポートを「有効」にできた場合、Windows 7でこの機能は最終的にシステムから「カット」されました。 また、ユーザーに何らかの種類のdllをシステムフォルダーにコピーさせることも、「コーシャではありません」。
再びGoogleに目を向けると、いくつかの解決策があります。 いずれにせよ、すべてのオプションは、ANSIエスケープシーケンスをWinAPI呼び出しに置き換えてコンソール属性を管理することを要約しています。
しばらくリンクをさまよった後、
コロラマプロジェクトに
出会いました。 どういうわけか私は彼が他の人よりも好きだった。 この特定のプロジェクトの利点には、コンソール出力全体の置換が含まれます-
print u"\x1b[31;40m- \x1b[0m"
したい場合は、単純な
print u"\x1b[31;40m- \x1b[0m"
色付きテキストを印刷できます。
現在のバージョン0.1.18には、Unicode行の出力を中断する迷惑な
バグが含まれていることがすぐにわかります。 しかし、問題を作成するときに、最も簡単なソリューションをそこにもたらしました。
実際には、両方の希望を組み合わせて、従来の「クランチ」の代わりに使い始めることが残っています。
さらにプロジェクトでは、実行ファイルで次を使用します。
それだけです 潜在的な改善のうち、同じStackOverflowでのより複雑な例のように、win64 pythonでの操作性を確認し、可能であれば、ColoredHandlerにisattyを確認させることが残っています。
結果のモジュールの最終バージョンは、
dumpz.orgで
入手できます。