2012-05-06 41 views
7

Tôi đã viết một chương trình để thêm (giới hạn) unicode support vào Python regexes, và trong khi nó hoạt động tốt trên CPython 2.5.2 nó không hoạt động trên PyPy ( 1.5.0-alpha0 1.8.0, triển khai Python 2.7.1 2.7.2), cả hai đều chạy trên Windows XP (Chỉnh sửa: như đã thấy trong nhận xét, @dbaupp có thể chạy tốt trên Linux). Tôi không biết tại sao, nhưng tôi nghi ngờ nó có liên quan đến việc sử dụng của tôi là u"ur". Nguồn tin đầy đủ là here, và các bit liên quan là:Unicode, cụm từ thông dụng và 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) 

(trên PyPy không có trận đấu trong "sử dụng Ví dụ", do đó resultNone)

nhắc lại, chương trình hoạt động tốt (trên CPython): dữ liệu Unicode có vẻ chính xác, thay thế hoạt động như dự định, ví dụ sử dụng chạy ok (cả hai thông qua doctest và trực tiếp gõ nó trong dòng lệnh). Mã hóa tệp nguồn cũng chính xác và chỉ thị coding trong tiêu đề dường như được nhận dạng bởi Python.

Bất kỳ ý tưởng nào về những gì PyPy có "khác biệt" đang phá vỡ mã của tôi? Nhiều thứ đến đầu của tôi (không được nhận dạng là tiêu đề coding, các mã hóa khác nhau trong dòng lệnh, các cách giải thích khác nhau của ru), nhưng theo như thử nghiệm của tôi, CPython và PyPy có vẻ hoạt động giống nhau, vì vậy tôi không biết phải làm gì hãy thử tiếp theo.

+1

Có lý do cụ thể nào bạn đang sử dụng phiên bản PyPy không ổn định cũ không? (Phiên bản ổn định mới nhất là 1.8.) – huon

+1

Ngoài ra, ví dụ cho các công trình tốt cho tôi sử dụng '[PyPy 1.8.0 với GCC 4.4.3] trên linux2'. Vì vậy, có vẻ như điều để thử tiếp theo là nâng cấp PyPy của bạn. – huon

+0

@dbaupp uh ...bacause đó là những gì được cài đặt trên máy tính của tôi? (hey, nó đã được mới khi tôi cài đặt nó ...) Bây giờ, nghiêm túc, tôi chỉ cần nâng cấp nó lên 1.8.0 và vẫn nhận được kết quả tương tự. Kể từ khi bạn quản lý để làm cho nó hoạt động trên Linux, có thể vấn đề được giới hạn cho Windows sau đó. Tôi sẽ điều tra thêm. – mgibsonbr

Trả lời

6

Dường như PyPy có một số sự cố mã hóa, cả khi đọc tệp nguồn (không được nhận dạng coding tiêu đề, có thể) và khi nhập/xuất trong dòng lệnh. Tôi đã thay thế mã ví dụ của mình bằng các thông tin sau:

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

Và nó tiếp tục hoạt động trên CPython và thất bại trên PyPy. Thay thế "á" cho các ký tự thoát của nó - u'\xe1\xc7\xf1' - OTOH đã thực hiện thủ thuật:

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

Điều đó làm việc tốt trên cả hai. Tôi tin rằng vấn đề được giới hạn trong hai kịch bản này (tải nguồn và dòng lệnh), vì cố mở một tệp UTF-8 bằng cách sử dụng codecs.open hoạt động tốt. Khi tôi cố gắng để nhập chuỗi "ACN" trong dòng lệnh, hoặc khi tôi tải mã nguồn của "unicode_hack.py" sử dụng codecs, tôi nhận được kết quả tương tự trên CPython:

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

nhưng kết quả khác nhau trên PyPy:

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

cập nhật:Issue1139 nộp PyPy hệ thống theo dõi lỗi, chúng ta hãy xem làm thế nào mà hóa ra ...

7

Tại sao bạn không chỉ đơn giản là sử dụng Matthew Barnett’s super-recommended regexp module thay vào đó?

Nó hoạt động trên cả Python 3 và Python 2 kế thừa, là một thay thế thả cho re, xử lý tất cả các công cụ Unicode bạn có thể muốn, và nhiều hơn nữa.

+0

Chắc chắn, tôi đã xem xét sử dụng các công cụ regex khác (ví dụ như Ponyguruma chẳng hạn), tôi có thể đi với đề xuất của bạn cuối cùng, cảm ơn! Nhưng vấn đề ở đây hóa ra không phải về regex, nhưng hỗ trợ unicode trên PyPy trên Windows (tất nhiên, khi tôi hỏi câu hỏi tôi không biết nó là gì, nên vấn đề với regex là một khả năng). BTW chỉ thấy rằng [báo cáo lỗi] (https://bugs.pypy.org/issue1139) đã được xác nhận. – mgibsonbr

Các vấn đề liên quan