web-dev-qa-db-ja.com

Unicodeを大文字に変換して印刷するにはどうすればよいですか?

私はこれを持っています:

>>> print 'example'
example
>>> print 'exámple'
exámple
>>> print 'exámple'.upper()
EXáMPLE

印刷するために必要なこと:

EXÁMPLE

( 'a'はアクセントがアクセントになりますが、大文字です)

Python 2.6を使用しています。

38
Alex. S.

それはnotと同じくらい簡単だと思いますASCII最初に変換します。

 >>> print u'exámple'.upper()
 EXÁMPLE
59
tylerl

python 2.xでは、upper()を呼び出す前に文字列をユニコードに変換するだけです。このWebページのutf-8形式のコードを使用します。

_>>> s = 'exámple'
>>> s
'ex\xc3\xa1mple'  # my terminal is not utf8. c3a1 is the UTF-8 hex for á
>>> s.decode('utf-8').upper()
u'EX\xc1MPLE'  # c1 is the utf-16 aka unicode for á
_

decodeを呼び出すと、現在の形式からUnicodeに変換されます。その後、encodeを使用して、utf-8などの他の形式に変換できます。たとえば、文字がiso-8859-2(この場合はチェコ語など)に含まれている場合は、代わりにs.decode('iso-8859-2').upper()を使用します。

私の場合と同様に、端末がunicode/utf-8に準拠していない場合は、文字の16進表記(私のものなど)を使用するか、s.decode('utf-8').upper().encode('ascii', 'replace')を使用して非可逆的に変換するのが最善です。結果は「EX?MPLE」になります。端末にUnicodeを表示できない場合は、出力をutf-8形式のファイルに書き込んで、お気に入りのエディターで開きます。

18
Jarret Hardie

最初に、私は最近python 3.1のみを使用します。その主なメリットは、Unicodeオブジェクトからバイト文字列を明確にすることです。これにより、テキスト操作の大部分が以前よりもはるかに安全になります。 python 2.xエンコーディングの問題に関する何兆ものユーザーの質問を考慮に入れて、python 2.1の_u'äbc_規約は単なる間違いでした;明示的にbytesbytearray、人生はとても簡単になります。

次に、py3kが好みではない場合、_from __future__ import unicode_literals_を使用してみてください。これは、python 2.6および2.7でのpy3kの動作を模倣するためです。このことにより、(簡単にコミットされる)print 'exámple'.upper()と言ったときの失敗本質的に、これはpy3kと同じです:print( 'exámple'.encode( 'utf-8' ).upper() )。これらのバージョンを比較します(py3kの場合):

_print( 'exámple'.encode( 'utf-8' ).upper() )
print( 'exámple'.encode( 'utf-8' ).upper().decode( 'utf-8' ) )
print( 'exámple'.upper() )
_

最初のものは、基本的に、デフォルトのエンコーディングを_'exámple'_に設定した場合に、裸の文字列_utf-8_を使用したときに実行したことです(BDFL宣言に従って、実行時にデフォルトのエンコーディングを設定することは悪いことです)アイデアなので、py2ではimport sys; reload( sys ); sys.setdefaultencoding( 'utf-8' )と言って騙す必要があります。以下のpy3kのより良い解決策を紹介します)。次の3行の出力を見ると、

_b'EX\xc3\xa1MPLE'
EXáMPLE
EXÁMPLE
_

upper()が最初のテキストに適用されると、文字ではなくバイトに作用することがわかります。 pythonはバイトでupper()メソッドを許可しますが、バイトのUS-ASCII解釈でのみ定義されます。utf-8は値を使用するためwithin8ビットですが、US-ASCIIのoutside(128から255まで、米国では使用されていません) -ASCII)、これらはupper()の影響を受けないため、2行目でデコードすると小文字の_á_が返されます。最後に、3行目で正しく処理されます。はい、驚きです、pythonは_Á_が_á_に対応する大文字であることを認識しているようです。簡単なテストを実行して、どの文字を確認したかpython 3は大文字と小文字を変換しません:

_for cid in range( 3000 ):
  my_chr = chr( cid )
  if my_chr == my_chr.upper() and my_chr == my_chr.lower():
    say( my_chr )
_

リストをよく読んでみると、ラテン文字、キリル文字、ギリシャ文字の出現はほとんどありません。出力のほとんどは、非ヨーロッパ文字と句読点です。 pythonが間違っているとわかった唯一の文字はԤ/ԥ(\ u0524、\ u0525、 'cyrillic {capital | small} letter pe with descender')です。ラテン語のExtended-Xブロックの外(それらを確認してください。驚かれるかもしれません)、実際にその方法を使用する可能性があります。もちろん、マッピングの正確さは確認していません。

最後に、これが私がpy3kアプリケーションのブートセクションに追加したものです。フォールバックとして数値文字参照(NCR)を使用して、_sys.stdout_のエンコードを再定義するメソッド。これにより、標準出力に出力しても、Unicodeエンコーディングエラーが発生することはありません。私がubuntuで作業するとき、__sys.stdout.encoding_は_utf-8_です;同じプログラムをWindowsで実行すると、_cp850_のような趣のあるものになる可能性があります。出力は厳しく見えるかもしれませんが、アプリケーションはこれらの薄暗い端末で例外を発生させることなく実行されます。

_#===========================================================================================================
# MAKE STDOUT BEHAVE IN A FAILSAFE MANNER
#-----------------------------------------------------------------------------------------------------------
def _harden_stdout():
  """Ensure that unprintable output to STDOUT does not cause encoding errors; use XML character references
  so any kind of output gets a chance to render in a decipherable way."""
  global _sys_TRM
  _sys.stdout       = _sys_TRM = _sys_io.TextIOWrapper(
    _sys.stdout.buffer,
    encoding        = _sys.stdout.encoding,
    errors          = 'xmlcharrefreplace',
    line_buffering  = true )
#...........................................................................................................
_harden_stdout()
_

もう1つのアドバイス:テスト時には、常にprint repr( x )またはxのアイデンティティを明らかにする同様のことを試みてください。 py2で_print x_を使用し、xがオクテット文字列またはUnicodeオブジェクトのいずれかである場合、あらゆる種類の誤解が生じる可能性があります。それは非常に不可解であり、多くの頭を引っかくことを引き起こしがちです。私が言ったように、将来のインポートユニコードリテラルの呪文から、少なくともpy26に移動するようにしてください。

最後に、引用を引用します: "Glyph Lefkowitzが彼の記事で最もよく述べています Encoding

この議論の文脈では、「文字列」という用語は無意味だと思います。テキストがあり、バイト指向のデータがあります(テキストを非常によく表している可能性がありますが、まだ変換されていません)。 Python型では、テキストはユニコードです。データはstrです。「非ユニコードテキスト」の考え方は、発生するのを待っているプログラミングエラーです。 "

更新:見つかりましたpython 3大文字にすると、ラテン小文字の長いSがSに正しく変換されます。きちんと!

9
flow

ここで見逃している背景が少しあると思います。

>>> type('hello')
<type 'str'>

>>> type(u'hello')
<type 'unicode'>

「ネイティブ」文字列ではなく「ユニコード」文字列を使用している限り、upper()などの演算子はユニコードを考慮して動作します。 FWIW、Python 3はデフォルトでユニコードを使用するため、区別はほとんど関係ありません。

文字列をunicodeからstrに取得してからunicodeに戻すことは、多くの点で最適ではありません。多くのライブラリでは、必要に応じてUnicode出力を生成します。したがって、できる限り、内部では文字列にunicodeオブジェクトのみを使用するようにしてください。

4
tylerl