362

Python プログラムの出力をパイプ処理するとき、Python インタープリターはエンコーディングについて混乱し、None に設定します。これは、次のようなプログラムを意味します。

# -*- coding: utf-8 -*-
print u"åäö"

通常の実行では問題なく動作しますが、次の場合に失敗します。

UnicodeEncodeError: 'ascii' コーデックは位置 0 の文字 u'\xa0' をエンコードできません: 序数が範囲外です (128)

パイプ シーケンスで使用する場合。

配管時にこれを機能させる最良の方法は何ですか? シェル/ファイルシステム/使用しているエンコーディングを使用するように指示できますか?

これまでに見た提案は、site.py を直接変更するか、このハックを使用して defaultencoding をハードコーディングすることです。

# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"

配管を機能させるより良い方法はありますか?

4

11 に答える 11

169

Python は出力を端末アプリケーションが使用しているエンコードにエンコードするため、スクリプトで実行するとコードが機能します。パイプする場合は、自分でエンコードする必要があります。

経験則は次のとおりです。常に内部で Unicode を使用します。受信したものをデコードし、送信したものをエンコードします。

# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')

もう 1 つの教訓的な例は、ISO-8859-1 と UTF-8 の間ですべてを大文字に変換する Python プログラムです。

import sys
for line in sys.stdin:
    # Decode what you receive:
    line = line.decode('iso8859-1')

    # Work with Unicode internally:
    line = line.upper()

    # Encode what you send:
    line = line.encode('utf-8')
    sys.stdout.write(line)

システムのデフォルトのエンコーディングを設定することはお勧めできません。なぜなら、使用するモジュールやライブラリの中には、それが ASCII であるという事実に依存するものがあるからです。やらないでください。

于 2009-01-29T18:03:18.150 に答える
168

まず、このソリューションについて:

# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')

毎回特定のエンコーディングで明示的に印刷するのは実用的ではありません。それは反復的でエラーが発生しやすいものです。

より良い解決策は、プログラムの開始時に変更sys.stdoutして、選択したエンコーディングでエンコードすることです。Pythonで見つけた解決策の 1 つを次に示します。、特に「toka」さんのコメント:

import sys
import codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
于 2009-07-23T02:05:58.510 に答える
138

環境変数「PYTHONIOENCODING」を「utf_8」に変更してみてください。私は、この問題に関する私の試練についてのページを書きました。

ブログ投稿の Tl;dr:

import sys, locale, os
print(sys.stdout.encoding)
print(sys.stdout.isatty())
print(locale.getpreferredencoding())
print(sys.getfilesystemencoding())
print(os.environ["PYTHONIOENCODING"])
print(chr(246), chr(9786), chr(9787))

あなたにあげる

utf_8
False
ANSI_X3.4-1968
ascii
utf_8
ö ☺ ☻
于 2010-10-26T20:30:35.287 に答える
63
export PYTHONIOENCODING=utf-8

仕事をしますが、Python自体に設定することはできません...

私たちができることは、設定されていないかどうかを確認し、スクリプトを呼び出す前に設定するようにユーザーに指示することです:

if __name__ == '__main__':
    if (sys.stdout.encoding is None):
        print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
        exit(1)

コメントに返信するように更新: stdout にパイプするときに問題が発生するだけです。Fedora 25 Python 2.7.13でテストしました

python --version
Python 2.7.13

猫b.py

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import sys

print sys.stdout.encoding

./b.py を実行中

UTF-8

実行中./b.py | 以下

None
于 2011-06-15T18:40:18.733 に答える
5

先週も同様の問題がありました。IDE (PyCharm) で修正するのは簡単でした。

これが私の修正でした:

PyCharm メニュー バーから開始: ファイル -> 設定... -> エディター -> ファイル エンコーディング、次に設定: 「IDE エンコーディング」、「プロジェクト エンコーディング」、および「プロパティ ファイルのデフォルト エンコーディング」をすべて UTF-8 にすると、彼女は動作するようになりました。魔法のように。

お役に立てれば!

于 2015-06-21T02:54:18.990 に答える
4

クレイグ・マックイーンの答えの議論の余地のあるサニタイズされたバージョン。

import sys, codecs
class EncodedOut:
    def __init__(self, enc):
        self.enc = enc
        self.stdout = sys.stdout
    def __enter__(self):
        if sys.stdout.encoding is None:
            w = codecs.getwriter(self.enc)
            sys.stdout = w(sys.stdout)
    def __exit__(self, exc_ty, exc_val, tb):
        sys.stdout = self.stdout

使用法:

with EncodedOut('utf-8'):
    print u'ÅÄÖåäö'
于 2015-04-13T10:24:12.263 に答える
2

次の呼び出しで「自動化」できます。

def __fix_io_encoding(last_resort_default='UTF-8'):
  import sys
  if [x for x in (sys.stdin,sys.stdout,sys.stderr) if x.encoding is None] :
      import os
      defEnc = None
      if defEnc is None :
        try:
          import locale
          defEnc = locale.getpreferredencoding()
        except: pass
      if defEnc is None :
        try: defEnc = sys.getfilesystemencoding()
        except: pass
      if defEnc is None :
        try: defEnc = sys.stdin.encoding
        except: pass
      if defEnc is None :
        defEnc = last_resort_default
      os.environ['PYTHONIOENCODING'] = os.environ.get("PYTHONIOENCODING",defEnc)
      os.execvpe(sys.argv[0],sys.argv,os.environ)
__fix_io_encoding() ; del __fix_io_encoding

はい、この「setenv」が失敗すると、ここで無限ループが発生する可能性があります。

于 2012-03-15T09:59:11.367 に答える