2012-05-06 17 views
7

unicode supportをPython正規表現に追加するプログラムを書いていますが、CPython 2.5.2では問題なく動作していますが、PyPy( 1.5.0-alpha0 1.8.0、 Python 2.7.1 2.7.2を実装していて、どちらもWindows XPで動作しています(編集:コメントに見られるように、@dbauppはLinux上でうまく動作します)。なぜ私は考えていませんが、私はu"ur"の私の用途と関係があると考えています。 (上Unicode、正規表現とPyPy

# -*- coding:utf-8 -*- 
import re 

# Regexps to match characters in the BMP according to their Unicode category. 
# Extracted from Unicode specification, version 5.0.0, source: 
# http://unicode.org/versions/Unicode5.0.0/ 
unicode_categories = { 
    ur'Pi':ur'[\u00ab\u2018\u201b\u201c\u201f\u2039\u2e02\u2e04\u2e09\u2e0c\u2e1c]', 
    ur'Sk':ur'[\u005e\u0060\u00a8\u00af\u00b4\u00b8\u02c2-\u02c5\u02d2-\u02df\u02...', 
    ur'Sm':ur'[\u002b\u003c-\u003e\u007c\u007e\u00ac\u00b1\u00d7\u00f7\u03f6\u204...', 
    ... 
    ur'Pf':ur'[\u00bb\u2019\u201d\u203a\u2e03\u2e05\u2e0a\u2e0d\u2e1d]', 
    ur'Me':ur'[\u0488\u0489\u06de\u20dd-\u20e0\u20e2-\u20e4]', 
    ur'Mc':ur'[\u0903\u093e-\u0940\u0949-\u094c\u0982\u0983\u09be-\u09c0\u09c7\u0...', 
} 

def hack_regexp(regexp_string): 
    for (k,v) in unicode_categories.items(): 
     regexp_string = regexp_string.replace((ur'\p{%s}' % k),v) 
    return regexp_string 

def regex(regexp_string,flags=0): 
    """Shortcut for re.compile that also translates and add the UNICODE flag 

    Example usage: 
     >>> from unicode_hack import regex 
     >>> result = regex(ur'^\p{Ll}\p{L}*').match(u'áÇñ123') 
     >>> print result.group(0) 
     áÇñ 
     >>> 
    """ 
    return re.compile(hack_regexp(regexp_string), flags | re.UNICODE) 

(PyPyの「使用例」の一致がないので、resultNoneある)

改めて表明、プログラムが正常に動作します:完全なソースはhereであり、そして関連するビットでありますCPython):Unicodeデータが正しいように見え、置換が意図した通りに機能し、使用例が正常に実行されます(doctest経由で直接コマンドラインで入力します)。ソースファイルのエンコーディングも正しく、ヘッダーのcodingディレクティブがPythonによって認識されているようです。

PyPyが私のコードを壊している「違う」のアイデアはありますか?多くのことが私の頭に浮かびました(コマンドラインの認識されないcodingヘッダー、異なるエンコーディング、異なる解釈ru)が、私のテストに行く限り、CPythonとPyPyの両方が同じように動作するように見えるので、次に試してみてください。

+1

PyPyのような古い不安定なバージョンを使用している特別な理由はありますか? (最新の安定版は1.8です。) – huon

+1

また、与えられた例は 'linux2で' 'PyPy 1.8.0 with GCC 4.4.3 'を使ってうまく動作します。だから、あなたのPyPyをアップグレードすることが次の試みのように見えます。 – huon

+0

@dbaupp uh ...私のマシンに何がインストールされているのでしょうか? (ちょっと、私がインストールしたときに新しいものだった...)真剣に、私は1.8.0にアップグレードしても同じ結果が得られました。あなたはそれがLinux上で動作するように管理して以来、おそらく問題はWindowsに限られています。私はさらに調査します。 – mgibsonbr

答えて

6

ソースファイル(認識されないcodingヘッダー、多分)を読み込んだり、コマンドラインで入力/出力するときに、PyPyにエンコードの問題があります。私は私の例のコードを次のように置き換えました:

それはCPythonで動作し続けていて、PyPyで失敗しました。そのエスケープ文字に「ACN」を交換 - u'\xe1\xc7\xf1' - 大藤はトリックでした:

>>> from unicode_hack import regex 
>>> result = regex(ur'^\p{Ll}\p{L}*').match(u'\xe1\xc7\xf1123') 
>>> print result.group(0) == u'\xe1\xc7\xf1' 
True 
>>> 

の両方でうまく働きました。 codecs.openを使用してUTF-8ファイルを開こうとするとうまく動作するので、問題はこれらの2つのシナリオ(ソースロードとコマンドライン)に限定されていると私は考えています。私は、コマンドラインで入力した文字列「ACN」を試すか、私はcodecsを使用して「unicode_hack.py」のソースコードを読み込むとき、私はCPythonの上、同じ結果を取得する場合:

>>> u'áÇñ' 
u'\xe1\xc7\xf1' 
>>> import codecs 
>>> codecs.open('unicode_hack.py','r','utf8').read()[19171:19174] 
u'\xe1\xc7\xf1' 

が、上の異なる結果をPyPy:

>>>> u'áÇñ' 
u'\xa0\u20ac\xa4' 
>>>> import codecs 
>>>> codecs.open('unicode_hack.py','r','utf8').read()[19171:19174] 
u'\xe1\xc7\xf1' 

更新:Issue1139はPyPyバグ追跡システムに提出が、それは結局のところどのように見てみましょう...

7

なぜあなたは単にを使用していません代わりに3210?

これはPython 3と従来のPython 2の両方で動作し、reの置き換えであり、必要なすべてのUnicodeを扱います。

+0

もちろん、私は他の正規表現エンジン(例えばPonygurumaのようなもの)を使うことを考えましたが、最後にあなたの提案に行くかもしれません、ありがとう!しかし、ここでの問題は正規表現ではなく、PyPyのWindows上でのユニコードサポート(私が疑問に思ったときに私はそれが何であるか分からなかったので、正規表現の問題が考えられた) BTWは[バグレポート](https://bugs.pypy.org/issue1139)が確認されたばかりです。 – mgibsonbr