【问题标题】:Unicode, regular expressions and PyPyUnicode、正则表达式和 PyPy
【发布时间】:2012-05-15 07:23:09
【问题描述】:

我编写了一个程序来添加(有限)unicode support 到 Python 正则表达式,虽然它在 CPython 2.5.2 上运行良好,但在 PyPy (1.5.0-alpha0 1.8.0 ,实现 Python 2.7.1 2.7.2),两者都在 Windows XP 上运行(Edit: 如 cmets 所示,@dbaupp 可以在 Linux 上正常运行)。我不知道为什么,但我怀疑这与我对u"ur" 的使用有关。完整来源为here,相关位为:

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

重申,程序运行良好(在 CPython 上):Unicode 数据似乎正确,替换按预期运行,使用示例运行正常(通过 doctest 和直接在命令行中输入)。源文件编码也是正确的,header中的coding指令似乎可以被Python识别。

关于 PyPy 的“不同”行为是否会破坏我的代码的任何想法?许多事情浮现在我的脑海(无法识别的coding 标头,命令行中的不同编码,ru 的不同解释)但就我的测试而言,CPython 和 PyPy 的行为似乎相同,所以我我不知道下一步该尝试什么。

【问题讨论】:

  • 有什么特别的原因让您使用这种旧的不稳定版本的 PyPy? (最新的稳定版本是 1.8。)
  • 另外,给出的示例对我使用[PyPy 1.8.0 with GCC 4.4.3] on linux2 来说效果很好。所以看起来接下来要尝试的是升级你的 PyPy。
  • @dbaupp 呃...因为那是我机器上安装的东西? (嘿,当我安装它时它是新的......)现在,说真的,我刚刚将它升级到 1.8.0 并且仍然得到相同的结果。既然你设法让它在 linux 上运行,那么问题可能仅限于 Windows。我会进一步调查。
  • 啊,废话。 (作为记录,它对我来说直接有效,我刚刚下载了文件,运行了你的示例,一切都很好。)
  • @KarlKnechtel 可以。这可能是正确的(PyPy 中的一个错误),在将问题缩小到 Windows 系统后,我进行了进一步测试(请参阅下面的答案)并注意到在命令行中输入 Unicode 数据时行为不一致(未显示:打印时相同到屏幕)以及当数据来自文件时,使用codecs正确加载。

标签: python regex string unicode pypy


【解决方案1】:

你为什么不直接使用Matthew Barnett’s super-recommended regexp module 呢?

它适用于 Python 3 和旧版 Python 2,是 re 的直接替代品,可处理您可能需要的所有 Unicode 内容,以及更多功能。

【讨论】:

  • 当然,我考虑过使用其他正则表达式引擎(例如 Ponyguruma),最后我可能会接受您的建议,谢谢!但是这里的问题原来不是关于正则表达式,而是 Windows 上 PyPy 的 unicode 支持(当然,当我问这个问题时我不知道它是什么,所以正则表达式的问题是可能的)。 BTW 刚刚看到bug report 已经被确认了。
【解决方案2】:

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

这对双方都很好。我相信问题仅限于这两种情况(源加载和命令行),因为尝试使用 codecs.open 打开 UTF-8 文件可以正常工作。当我尝试在命令行中输入字符串“áÇñ”时,或者当我使用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 错误跟踪系统上提交,让我们看看结果如何...

【讨论】:

    猜你喜欢
    • 2010-09-06
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-16
    • 2017-01-25
    • 1970-01-01
    相关资源
    最近更新 更多