Pythonスクリプト内で、作成しなかった関数から文字列を取得します。それのエンコーディングは異なります。私はそれをASCII形式に変換する必要があります。これを行うための絶対確実な方法はありますか?非ASCII文字を空白などに置き換えてもかまいません...
5 に答える
情報を失うことなく、取得したものを明確に表す ASCII 文字列が必要な場合、答えは簡単です。
repr()
関数 (Python 2.X) またはascii()
関数 (Python 3.x)を使用してください。
あなたは「それのエンコーディングは変わる」と言います。「それ」とは、Python 2.xの「文字列」を意味していると思います。これは、実際にはバイトのシーケンスです。
パート1に答えてください:そのエンコードされた文字列のエンコードがわからない場合は、いいえ、それで意味のあることを行う方法はまったくありません*。エンコーディングを知っている場合、ステップ1はあなたを:に変換することstr
ですunicode
。
encoded_string = i_have_no_control()
the_encoding = 'utf-8' # for the sake of example
text = unicode(encoded_string, the_encoding)
次に、必要に応じて、UnicodeオブジェクトをASCIIとして再エンコードできます。
ascii_garbage = text.encode('ascii', 'replace')
*エンコーディングを推測するためのヒューリスティックな方法がありますが、それらは遅く、信頼性がありません。これがPythonでの優れた試みの1つです。
文字列を正規化してからエンコードしようとします。どうですか:
import unicodedata
s = u"éèêàùçÇ"
print unicodedata.normalize('NFKD',s).encode('ascii','ignore')
これは、入力としてUnicodeがある場合にのみ機能します。そのため、関数出力をエンコードしてデコードできるものを知っておく必要があります。そうでない場合は、エンコーディング検出ヒューリスティックがありますが、短い文字列では信頼性がありません。
もちろん、運が良ければ、関数の出力はさまざまな不明なエンコーディングに依存しますが、コードベースとしてASCIIを使用するため、0〜127のバイトに同じ値が割り当てられます(utf-8など)。
その場合、 OrderedSetsを使用して不要な文字をフィルタリングすることで、不要な文字を取り除くことができます。
import string.printable # asccii chars
print "".join(OrderedSet(string.printable) & OrderedSet(s))
または、代わりに空白が必要な場合:
print("".join(((char if char in string.printable else " ") for char in s )))
「翻訳」はあなたが同じことをするのを助けることができます。
あなたがこの幸運であるかどうかを知る唯一の方法はそれを試してみることです...時々、大きな太った幸運な日はどんな開発者も必要とするものです:-)
「フールプルーフ」とは、最もあいまいで不可能な入力でも関数が失敗しないことを意味します。つまり、関数にランダムなバイナリ データを入力しても、何があっても失敗することはありません。それが「フールプルーフ」の意味です。
次に、関数は目的のエンコーディングに変換するために最善を尽くします。理解できないゴミをすべて捨てなければならない場合、それはまったく問題なく、実際には最も望ましい結果です。なぜすべてのがらくたを回収しようとするのですか? ジャンクを捨てるだけです。Microsoft の何かを使用するだけのバカではなく、非標準の Microsoft の何かを使用するか、バイナリ データを送信しようとする非標準のバカだとユーザーに伝えてください。
私はまさにこれと同じニーズを持っています (私のニーズは PHP にありますが)、少なくとも私と同じくらい、時にはそれ以上の馬鹿なユーザーもいます。ただし、それらは間違いなくより良く、間違いなくより忍耐強いです。
これまでに見つけた最高の結論は(PHP 5.3で)次のとおりです。
$fixed_string = iconv( 'ISO-8859-1', 'UTF-8//IGNORE//TRANSLATE', $in_string );
これは可能な限り翻訳を試み、すべてのジャンクを単純に破棄するため、正当な UTF-8 文字列出力が得られます。また、バイナリジャンクデータの塊を供給しても、それを壊したり、失敗したり、着信テキストやデータを拒否したりすることはできませんでした.
iconv() を見つけて動作させるのは簡単です。非常に腹立たしく無駄なことは、このエンコーディングの大失敗に対処するときに非常に多くのプログラマーが支持しているように見える、すべてのゴミと後ろ向きのばかげたことをすべて読むことです。古い学校のプログラミングのうらやましい (そして立派な) "Flail and Burn The Idiots" の考え方はどうなったのでしょうか? 基本に戻りましょう。iconv() を使用してゴミを捨て、ゴミを捨てたことを伝えるときに恥ずかしがらないでください。そして、あなたは私があなたにそう言ったと彼らに言うことができます.
ASCII互換の文字を保持し、残りを破棄するだけの場合、ほとんどのエンコーディングでは、上位ビットが設定されているすべての文字、つまり値が127を超える文字を削除することになります。これはほぼすべての文字が機能するためです。文字セットは7ビットASCIIの拡張です。
通常の文字列(つまり、ではないunicode
)の場合は、任意の文字セットでデコードiso-8859-1
してから(たとえば、任意のバイト値を受け入れるため)、エラーのignore
orreplace
オプションを使用してASCIIでエンコードする必要があります。
>>> orig = '1ä2äö3öü4ü'
>>> orig.decode('iso-8859-1').encode('ascii', 'ignore')
'1234'
>>> orig.decode('iso-8859-1').encode('ascii', 'replace')
'1??2????3????4??'
エンコードを使用するにはユニコード文字列が必要なため、デコード手順が必要です。すでにUnicode文字列を使用している場合は、次のようになります。
>>> orig = u'1ä2äö3öü4ü'
>>> orig.encode('ascii', 'ignore')
'1234'
>>> orig.encode('ascii', 'replace')
'1??2????3????4??'