2

次の簡単なプログラムがあります。

# -*- coding: utf-8 -*-

GREEK = u'ΑΒΓΔ ΕΖΗΘ ΙΚΛΜ ΝΞΟΠ ΡΣΤΥ ΦΧΨΩ αβγδ εζηθ ικλμ νξοπ ρςτυ φχψω'

print GREEK

これを端末で実行すると、期待どおりに次のようになります。

$ python test.py
ΑΒΓΔ ΕΖΗΘ ΙΚΛΜ ΝΞΟΠ ΡΣΤΥ ΦΧΨΩ αβγδ εζηθ ικλμ νξοπ ρςτυ φχψω

ただし、出力を別のプログラムにパイプすると、エラーが発生します。

$ python test.py | less

Traceback (most recent call last):
  File "test.py", line 5, in <module>
    print GREEK
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
Traceback (most recent call last):
  File "ddd.py", line 5, in <module>
    print GREEK
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
  • なぜこれが失敗するのですか?プログラムの実行方法にリダイレクトが影響するのはなぜですか? シェルで実行されるプログラムは常にリダイレクトされると予想していました。端末プログラムにリダイレクトされることもあれば、別のプログラムにリダイレクトされることもあります (lessこの場合)。「宛先」プログラムがソースプログラムの実行に影響を与えるのはなぜですか?
  • プログラムが端末に送信されるか別の宛先に送信されるかに関係なく、プログラムが確実に実行されるようにするにはどうすればよいですか?
4

2 に答える 2

7

これに基づいて、他の関連する質問に基づいて、次のソリューションを実装しました。これは非常に堅牢で、コードベースのすべての印刷ステートメントを変更する必要はありません。

# -*- coding: utf-8 -*-

import sys

def set_output_encoding(encoding='utf-8'):
    import sys
    import codecs
    '''When piping to the terminal, python knows the encoding needed, and
       sets it automatically. But when piping to another program (for example,
       | less), python can not check the output encoding. In that case, it 
       is None. What I am doing here is to catch this situation for both 
       stdout and stderr and force the encoding'''
    current = sys.stdout.encoding
    if current is None :
        sys.stdout = codecs.getwriter(encoding)(sys.stdout)
    current = sys.stderr.encoding
    if current is None :
        sys.stderr = codecs.getwriter(encoding)(sys.stderr)

GREEK = u'ΑΒΓΔ ΕΖΗΘ ΙΚΛΜ ΝΞΟΠ ΡΣΤΥ ΦΧΨΩ αβγδ εζηθ ικλμ νξοπ ρςτυ φχψω'

set_output_encoding()

print GREEK
print >> sys.stderr, GREEK

これをテストするには:

python ddd.py             # Do not pipe anything
python ddd.py | less      # Pipe stdout, let stderr go to the terminal
python ddd.py 2>&1 | less # Pipe both stdout and stderr to less

それらはすべて、期待されるものを生成します。

ΑΒΓΔ ΕΖΗΘ ΙΚΛΜ ΝΞΟΠ ΡΣΤΥ ΦΧΨΩ αβγδ εζηθ ικλμ νξοπ ρςτυ φχψω
ΑΒΓΔ ΕΖΗΘ ΙΚΛΜ ΝΞΟΠ ΡΣΤΥ ΦΧΨΩ αβγδ εζηθ ικλμ νξοπ ρςτυ φχψω
于 2013-10-31T07:49:01.537 に答える
0

出力プログラムのエンコーディングが文字をサポートしていません。別の方法は、プログラムから出てくるものは常にエンコードし、必要なときにデコードして戻すことです。

# -*- coding: utf-8 -*-

GREEK = u'ΑΒΓΔ ΕΖΗΘ ΙΚΛΜ ΝΞΟΠ ΡΣΤΥ ΦΧΨΩ αβγδ εζηθ ικλμ νξοπ ρςτυ φχψω'

print GREEK.encode('utf-8')

これは機能しますが、端末アプリケーションが同じエンコーディングを使用していないため、元の文字列ではなく、エンコードされた文字列のみが表示されます。

于 2013-10-31T01:10:30.750 に答える