2012-05-06 2 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". Полный источник here, и соответствующие биты: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 нет матча в «примере использования», так result является None)

вновь заявляя, что программа работает отлично (на CPython): данные Юникода кажутся правильными, замена работает по назначению, пример использования работает нормально (оба через doctest и непосредственно вводят его в командной строке). Исходная кодировка файлов также правильна, и директива coding в заголовке, по-видимому, распознается Python.

Любые идеи о том, что PyPy делает «разные», что нарушает мой код? Множество вещей приходило мне в голову (непризнанный заголовок coding, разные кодировки в командной строке, разные интерпретации r и u), но, насколько мне известно, как CPython, так и PyPy, похоже, ведут себя одинаково, поэтому я не знаю, что попробуйте следующий.

+1

Есть ли какая-то конкретная причина, по которой вы используете такую ​​старую нестабильную версию PyPy? (Последняя стабильная версия - 1.8.) – huon

+1

Также приведенный ниже пример отлично подходит для меня, используя '[PyPy 1.8.0 с GCC 4.4.3] на linux2'. Таким образом, похоже, что нужно попробовать, это обновить PyPy. – huon

+0

@dbaupp uh ...bacause - это то, что установлено на моей машине? (эй, это было ново, когда я его установил ...) Теперь, серьезно, я только что обновил его до 1.8.0 и все еще получал те же результаты. Поскольку вам удалось заставить его работать на Linux, возможно, проблема ограничивается Windows. Я буду исследовать дальше. – mgibsonbr

ответ

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' - Ото сделал трюк:

>>> 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 отлично работает. Когда я пытаюсь ввести строку «АКС» в командной строке, или когда я загрузить исходный код «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' 

Update:Issue1139 представленный на PyPy системы слежения ошибка, давайте посмотрим, как это получается ...

7

Почему вы не просто использовать Matthew Barnett’s super-recommended regexp module инст EAD?

Он работает как на Python 3, так и на устаревшем Python 2, является заменой на re, обрабатывает все необходимые вам Unicode-файлы и многое другое.

+0

Конечно, я рассмотрел использование других двигателей регулярных выражений (например, Ponyguruma), я могу пойти с вашим предложением в конце, спасибо! Но проблема здесь заключалась не в регулярных выражениях, а в поддержке юникода на PyPy на Windows (разумеется, когда я задал вопрос, я не знал, что это было, поэтому проблема с регулярными выражениями была возможностью). BTW только что увидел, что [отчет об ошибке] (https://bugs.pypy.org/issue1139) подтвержден. – mgibsonbr

Смежные вопросы