2016-09-28 4 views
3

問題
これをペルシア語の文字に遭遇した)。 chcp 65001コードページでPythonを使用して、1つのUnicode文字を入力しようとすると、Pythonはエラーなしで終了します。CHCP 65001のコードページの結果

私はこの問題を無駄に解決しようと努力しました。しかし今日、私はpython websiteのスレッドを見つけました。もう1つはMySQLです。もう1つの解決策や説明がなくても、Lua-usersはこの突然の終了に関する問題を提起しています。chcp 65001は本質的に壊れています。

この問題がchcp-design-relatedであるか、回避策があるかを一度知っておくとよいでしょう。

再現エラー

chcp 65001

Pythonの3.X:

Pythonがシェル

print('ä')

結果は:それはちょうど

しかしシェルを終了し、これはpython.exe -c "print('ä')" との作品もこの:print('\u00e4')

結果:

print('ä')

Luajit2.0.4で

ä

結果:私はこれまでの観測が出ているprint('\xc3\xa4')

:コマンドプロンプト作品と

  1. 直接出力、それだけで

    しかし、この作品のシェルを終了します。

  2. 文字のUnicodeベースの16進数に相当する文字が動作します。

だから これは(私がCmderを使用しています私たちは、WindowsのコマンドプロンプトやConemu、CmderのようなそのラッパーのいずれかにCLIプログラムで直接Unicode文字を使用することはできませんPythonのバグではありませんWindowsシェルでUnicode文字を見たり使えるようにするために、問題なく使用しました。これは正しいです?

+0

多くのPythonバージョンがインストールされています。 Windows 10 64ビット版、Python 3.3.5 64ビット版、またはPython 3.5.2 64ビット版では再現できませんでしたが、Python 2.7.12 32ビット版では再現できませんでした。これは説明したように終了しますが、あなたはPython 3を使用していると言いました。おそらく、32ビットと64ビットのどちらの問題でしょうか? Windowsのcmd.exeコンソールなどを使用していますか? –

+0

@MarkTolonenこれは、コードページ65001用に設計されていないコンソール(conhost; cmdは単なるシェル)を使用すると、すべてのWindowsバージョンで再現可能です。ASCII以外の文字を1つ入力すると、空読み込みが発生します。 'input'をEOFとして扱います。問題はconhost.exeがUTF-16入力バッファーをANSIコードページにエンコードして1文字あたり1バイトであると仮定しているため、ASCII以外のUTF-8では 'WideCharToMultiByte'エンコードバッファーが小さすぎます。読み込みは失敗しますが、0バイトの「成功した」読み込み、つまりファイルの終わりとしてクライアントに返されます。 – eryksun

+0

@eryksun、はい、壊れていますが、64ビット版のWindows 10上の64ビットPythonでは、国際化IMEでcmd.exe 'print( 'ä')'をタイプして印刷できます正しくしたがって、少なくともこの特定の例では、「すべてのWindowsで再現可能」バージョンが不正確です。 –

答えて

5

WindowsコンソールでPython 2用のUnicodeを使用する。7および3.x(3.6以前)では、win_unicode_consoleをインストールして有効にします。これは、cmd.exeやpowershell.exeなどの他のUnicode対応のコンソールプログラムと同様に、ワイド文字関数ReadConsoleWWriteConsoleWを使用します。 Python 3.6では、新しいio._WindowsConsoleIOローI/Oクラスが追加されました。 UTF-8でエンコードされたテキストを読み書きします(Unixとのクロスプラットフォーム互換 - "get a byte" - プログラム)が、内部的にはUTF-16LEとの間でトランスコードすることでワイドキャラクタAPIを使用します。

ASCII以外の入力で発生する問題は、Windows 10以降のすべてのWindowsバージョンでコンソールで再現可能です。コンソールホストプロセス(conhost.exe)は、UTF-8用に設計されていませんコードページ65001)、それを一貫してサポートするように更新されていません。特に、非ASCII入力は空の読み取りを引き起こします。これにより、PythonのREPLが終了し、組み込みのinputEOFErrorを呼び出すようになります。

問題は、conhostが西洋ロケールのOEMコードとANSIコードページなどのシングルバイトコードページ(たとえば437,850,1252)を想定して、そのUTF-16入力バッファをエンコードすることです。 UTF-8は、非ASCII文字が2〜4バイトとしてエンコードされたマルチバイトエンコーディングです。 UTF-8を処理するには、M/4文字の複数の反復でエンコードする必要があります。ここで、MはNバイトバッファから利用可能な残りのバイトです。代わりに、Nバイトを読み取る要求がN文字を読み取る要求であると仮定します。次に、入力に1つ以上のASCII以外の文字が含まれていると、内部のWideCharToMultiByte呼び出しがバッファーサイズが小さすぎるために失敗し、コンソールは0バイトの「成功した」読み取りを返します。

pyreadlineモジュールがインストールされている場合、この問題がPython 3.5で正確に観察されないことがあります。 Python 3.5は自動的にreadlineをインポートしようとします。 pyreadlineの場合、入力はワイド文字関数ReadConsoleInputWによって読み込まれます。これは、コンソール入力レコードを読み取るための低レベル関数です。原則として動作するはずですが、実際にはprint('ä')と入力すると、REPLによってprint('')と読み込まれます。非ASCII文字の場合、ReadConsoleInputWはAlt + Numpad KEY_EVENTレコードのシーケンスを返します。シーケンスは損失のあるOEMエンコードであり、最後のレコード(入力文字はUnicodeCharフィールドにあります)を除いて無視できます。明らかに、pyreadlineはシーケンス全体を無視します。

Windows 8以前では、コードページ65001を使用した出力も破損していました。これは、非ASCII文字の数に比例したガベージテキストの軌跡を表示します。この場合、問題は、WriteFileWriteConsoleAが、UTF-8バイトの数ではなく、画面バッファに書き込まれたUTF-16コードの数を間違って返すことです。これは、Pythonのバッファライタを混乱させ、残りの未書き込みバイトであると思われるものを繰り返し書き込むことにつながります。この問題は、LPCポートの代わりにConDrvデバイスを使用するために内部コンソールAPIを書き換える際に、Windows 8で修正されました。古いバージョンのWindowsでは、ConEmuまたはANSICONを使用してこのバグを回避できます。

関連する問題