2009年03月13日

IPythonでunicodeリテラルを使う

はてなブックマークに登録

IPythonとは

IPythonとは、Pythonistaの中で絶大な人気を誇るインタラクティブシェルです。

Pythonはもともとインタラクティブシェルを内蔵しているのですが、 IPythonには内蔵のインタラクティブシェルと比べて多くの利点があります。いくつか挙げてみます。

  • 動的補完

    変数名などを途中まで入力した状態でTABキーを押すと、残りを補完してくれます。 候補が複数ある時は候補一覧を表示してくれます。

  • シンタックスハイライト

    プロンプトなどに色がつきます。ちょっとうれしいです。

  • 通常のシェルとしても利用可能

    IPythonの中で、lsでファイル一覧を見たり、cdでカレントディレクトリを移動したりできます。 !vim のようにエクスクラメーションマークに続いてコマンド名を入力することで、コマンドの実行もできます。 さらに、コマンドの出力がPythonの変数に格納され、Pythonから利用可能になります。Unixの大量のコマンドを使いこなせなかったり、Windowsでコマンドが少ないことが不満だったりするときに重宝します。

  • よく使う機能を省略形で記述可能

    help(o) の代わりに o? でそのオブジェクトのドキュメントが読めます。

    func(a, b) の代わりに func a b で関数呼び出しが可能です。

  • エディタと連携可能

    ed foo.py のようにすることで、 foo.py を外部エディタで開いて編集できます。 そしてエディタを閉じると、自動的にそのファイルがevalされます。 この機能を使うと、エディタで関数を書く→IPython上で動作を確認する→エディタで関数を修正する、というサイクルでサクサク開発できます。 これに馴れてしまうと、IDEが欲しいと思わなくなります。

IPythonでUnicodeリテラルを使う

IPython 0.9.1 でUnicodeリテラルを使おうとすると、次のような問題がありました

$ python
Python 2.5.2 (r252:60911, Oct  5 2008, 19:24:49)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> u"あ"
u'\u3042'
>>>
$ ipython
Python 2.5.2 (r252:60911, Oct  5 2008, 19:24:49)
Type "copyright", "credits" or "license" for more information.

IPython 0.9.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object'. ?object also works, ?? prints more.

In [1]: u"あ"
Out[1]: u'\xe3\x81\x82'

コンソールはUTF-8なので"あ" は3byteになっているのですが、それぞれのbyteを一文字と認識してUnicode文字に変換されています。

この問題を追ってみたところ、IPythonがPythonの組み込み関数 compile() を呼び出すときに、文字列をエンコードしてしまっているのに気づきました。 compile() の動作を調べて見たところ

>>> c = compile("""u'あ'""", "foo.py", 'single')
>>> c.co_consts
(u'\xe3\x81\x82', None)
>>> c = compile(u"""u'あ'""", "foo.py", "single")
>>> c.co_consts
(u'\u3042', None)

ビンゴです。

ということで、IPython/iplib.py に次の修正をすることで、IPythonでUnicodeリテラルが気持ちよく使えるようになります

--- iplib.py.old    2009-03-13 15:42:33.000000000 +0900
+++ iplib.py        2009-03-13 15:42:58.000000000 +0900
@@ -2019,9 +2019,9 @@
         # this allows execution of indented pasted code. It is tempting
         # to add '\n' at the end of source to run commands like ' a=1'
         # directly, but this fails for more complicated scenarios
-        source=source.encode(self.stdin_encoding)
-        if source[:1] in [' ', '\t']:
-            source = 'if 1:\n%s' % source
+        #source=source.encode(self.stdin_encoding)
+        if source[:1] in [u' ', u'\t']:
+            source = u'if 1:\n%s' % source

         try:
             code = self.compile(source,filename,symbol)

Windows (Python 2.6.1, IPython 0.9.1) でもうまく動くか確認して見ました

In [1]: u"あ"
Out[1]: u'\u3042'

In [2]: u"ソ"
Out[2]: u'\u30bd'

バッチリです


@methane
klab_gijutsu2 at 16:22│Comments(0)TrackBack(0)Python 

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント