7

Python 正規表現に (限定的な) Unicode サポートを追加するプログラムを作成しましたが、CPython 2.5.2 では正常に動作していますが、PyPy ( 1.5.0-alpha0 1.8.0、Python 2.7.1 2.7.2 を実装) では動作しません。どちらも Windows XP で実行されます (編集:コメントにあるように、@dbaapp は Linux で問題なく実行できます)。理由はわかりませんが、 と の使用に関係があると思われu"ますur"。完全なソースはここにあり、関連するビットは次のとおりです。

# -*- 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 では「使用例」に一致するものがないので、そうresultですNone)

繰り返しますが、プログラムは (CPython 上で) 正常に動作します: Unicode データは正しいようで、置換は意図したとおりに機能し、使用例は問題なく実行されます (doctestコマンド ラインでの直接入力と経由の両方)。ソースファイルのエンコーディングも正しく、codingヘッダーのディレクティブもPythonに認識されているようです。

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

4

2 に答える 2

7

代わりに 、 Matthew Barnettの超推奨regexpモジュールを使用しないのはなぜですか?

Python3とレガシーPython2の両方で動作し、のドロップイン置換でreあり、必要なすべてのUnicodeのものを処理します。

于 2012-05-06T22:13:13.367 に答える
6

PyPy には、ソース ファイルの読み取り時 (認識されないcodingヘッダーなど) と、コマンド ラインでの入力/出力の両方で、エンコードの問題があるようです。サンプルコードを次のように置き換えました。

>>> from unicode_hack import regex
>>> result = regex(ur'^\p{Ll}\p{L}*').match(u'áÇñ123')
>>> print result.group(0) == u'áÇñ'
True
>>>

そして、CPython で動作し続け、PyPy で失敗しました。エスケープされた文字の「áÇñ」を置き換えるu'\xe1\xc7\xf1'--OTOHはトリックを行いました:

>>> 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
>>>

それは両方でうまくいきました。を使用して UTF-8 ファイルを開こうとするとcodecs.open正常に動作するため、問題はこれら 2 つのシナリオ (ソースの読み込みとコマンド ライン) に限定されていると思います。コマンド ラインで文字列「áÇñ」を入力しようとすると、または を使用して「unicode_hack.py」のソース コードをロードするとcodecs、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 バグ追跡システムに提出されました。それがどうなるか見てみましょう...

于 2012-05-06T15:08:04.653 に答える