2015-11-01 11 views
8

पर कॉल करते समय सीमा में नहीं है, मुझे यूनिकोड इनपुट के साथ locale लाइब्रेरी का उपयोग करते समय एक अजीब व्यवहार का सामना करना पड़ रहा है। नीचे एक न्यूनतम कामकाजी उदाहरण है:यूनिकोड वर्ण locale.strxfrm

>>> x = '\U0010fefd' 
>>> ord(x) 
1113853 
>>> ord('\U0010fefd') == 0X10fefd 
True 
>>> ord(x) <= 0X10ffff 
True 
>>> import locale 
>>> locale.strxfrm(x) 
'\U0010fefd' 
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') 
'en_US.UTF-8' 
>>> locale.strxfrm(x) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: character U+110000 is not in range [U+0000; U+10ffff] 

मैंने इसे पायथन 3.3, 3.4 और 3.5 पर देखा है। मुझे पायथन 2.7 पर कोई त्रुटि नहीं मिली है।

जहाँ तक मैं देख सकता हूं, मेरा यूनिकोड इनपुट उपयुक्त यूनिकोड रेंज के भीतर है, इसलिए ऐसा लगता है कि किसी भी तरह से 'en_US.UTF-8' का उपयोग करते समय strxfrm में कुछ आंतरिक इनपुट को सीमा से बाहर ले जा रहा है।

मै मैक ओएस एक्स चला रहा हूं, और यह व्यवहार http://bugs.python.org/issue23195 से संबंधित हो सकता है ... लेकिन मुझे लगता है कि यह बग केवल गलत परिणामों के रूप में प्रकट होगा, अपवाद अपवाद नहीं। मैं अपनी एसएलएस 11 मशीन पर दोहराना नहीं कर सकता, और अन्य पुष्टि करते हैं कि वे उबंटू, सेंटोस या विंडोज पर दोहराना नहीं कर सकते हैं। टिप्पणियों में अन्य ओएस के बारे में सुनना निर्देशक हो सकता है।

कोई बता सकता है कि हुड के नीचे क्या हो रहा है?

+0

मैं इसे उबंटू पर पुन: पेश नहीं कर सकता। 'enale.strx-x' लोकेल में' locale.strxfrm (x) 'रिटर्न' 'x x \ x01 \ x01 \ x01 Ւ''। – jfs

+1

आप ['icu.Collator.createInstance (icu.Locale ('en_US') का उपयोग कर सकते हैं)। GetSortKey' इसके बजाय] (http://stackoverflow.com/a/32178778/4279) – jfs

+0

@JFSebastian हां, मैंने उपयोग किया है पीईआईसीयू और पुष्टि करें कि वहां कोई समस्या नहीं है। मैं stdlib 'locale' मॉड्यूल में इस व्यवहार के बारे में अधिक चिंतित था और यदि यह किसी प्रकार की उपयोगकर्ता त्रुटि थी (यानी मैंने कुछ गलत किया) या यदि कुछ और घबराहट चल रही है। – SethMMorton

उत्तर

7

पायथन 3.x में, फ़ंक्शन locale.strxfrm(s) आंतरिक रूप से POSIX C फ़ंक्शन wcsxfrm() का उपयोग करता है, जो वर्तमान LC_COLLATE सेटिंग पर आधारित है। POSIX मानक इस तरह से परिवर्तन को परिभाषित:

The transformation shall be such that if wcscmp() is applied to two transformed wide strings, it shall return a value greater than, equal to, or less than 0, corresponding to the result of wcscoll() applied to the same two original wide-character strings.

इस परिभाषा कई मायनों में लागू किया जा सकता है, और भी आवश्यकता नहीं है कि जिसके परिणामस्वरूप स्ट्रिंग पठनीय है।

मैं एक छोटे से सी कोड उदाहरण बना लिया है प्रदर्शित करने के लिए कि यह कैसे काम करता है:

#include <stdio.h> 
#include <wchar.h> 
#include <locale.h> 

int main() { 
    wchar_t buf[10]; 
    wchar_t *in = L"\x10fefd"; 
    int i; 

    setlocale(LC_COLLATE, "en_US.UTF-8"); 

    printf("in : "); 
    for(i=0;i<10 && in[i];i++) 
    printf(" 0x%x", in[i]); 
    printf("\n"); 

    i = wcsxfrm(buf, in, 10); 

    printf("out: "); 
    for(i=0;i<10 && buf[i];i++) 
    printf(" 0x%x", buf[i]); 
    printf("\n"); 
} 

यह पहले और परिवर्तन के बाद स्ट्रिंग प्रिंट करता है।

in : 0x10fefd 
out: 0x1 0x1 0x1 0x1 0x552 

जबकि यह OSX चल (10.11.1) परिणाम है::

लिनक्स पर यह चल रहा है (डेबियन जेसी) इस परिणाम है

in : 0x10fefd 
out: 0x103 0x1 0x110000 

आप देख सकते हैं कि ओएसएक्स पर wcsxfrm() के आउटपुट में वर्ण यू +110000 है जिसमें पाइथन स्ट्रिंग में अनुमति नहीं है, इसलिए यह त्रुटि का स्रोत है।

पायथन 2.7 पर त्रुटि नहीं उठाई गई है क्योंकि इसकी locale.strxfrm() कार्यान्वयन strxfrm() सी फ़ंक्शन पर आधारित है।

अद्यतन:

आगे जांच करते हुए, मुझे लगता है कि en_US.UTF-8 पर OSX के लिए LC_COLLATE परिभाषा la_LN.US-ASCII परिभाषा करने के लिए एक कड़ी है।

$ ls -l /usr/share/locale/en_US.UTF-8/LC_COLLATE 
lrwxr-xr-x 1 root wheel 28 Oct 1 14:24 /usr/share/locale/en_US.UTF-8/LC_COLLATE -> ../la_LN.US-ASCII/LC_COLLATE 

मुझे एप्पल से sources में वास्तविक परिभाषा मिली।

order \ 
    \x00;...;\xff 

2 अद्यतन: फ़ाइल la_LN.US-ASCII.src की सामग्री निम्नलिखित है

मैं आगे पर OSX wcsxfrm() समारोह परीक्षण किया है।

W1..Wn \x01 U1..Un 

जहां

Wx = 0x103 if Cx > 0xFF else Cx+0x3 
Ux = Cx+0x103 if Cx > 0xFF else Cx+0x3 

इस एल्गोरिथ्म \x10fefd का उपयोग करना बन 0x103 0x1 0x110000

: la_LN.US-ASCII कोलेट, विस्तृत चरित्र C1..Cn का एक अनुक्रम इनपुट के रूप में दिए गए का उपयोग करना, उत्पादन इस फार्म के साथ एक स्ट्रिंग है

मैंने जांच की है और प्रत्येक यूटीएफ -8 लोकेल ओएसएक्स पर इस कोलेट का उपयोग करता है, इसलिए मैं कहने के इच्छुक हूं कि एप्पल सिस्टम पर यूटीएफ -8 के लिए कोलेट समर्थन टूटा हुआ है। परिणामस्वरूप ऑर्डरिंग सामान्य यूनिकोड वर्ण प्राप्त करने की क्षमता के बोनस के साथ सामान्य बाइट तुलना के साथ प्राप्त की गई है।

+0

हू। तो ऐसा लगता है कि 'ValueError' को रोकने के लिए मैं इतना कुछ नहीं कर सकता क्योंकि यह पाइथन के नियंत्रण के बाहर अंतर्निहित सी लाइब्रेरी से आ रहा है। – SethMMorton

+0

मुझे आश्चर्य है कि यह एक बग माना जाएगा। मान लीजिए कि '0x110000'' wcsxfrm() 'के लिए वैध वापसी मान है, तो पाइथन आंतरिक रूप से इसे संभालने में सक्षम होना चाहिए, सही? हालांकि, अगर '0x110000' मान्य नहीं है तो मुझे लगता है कि पाइथन क्या कर रहा है" सही "होगा। – SethMMorton

+0

ऐसा लगता है कि यह 4 साल पहले आया था: https://mail.python.org/pipermail/python-dev/2011- दिसम्बर/114759.html और http://bugs.python.org/issue13441। मेरी आंखों से ऐसा नहीं लगता कि उन्हें मूल्यों के लिए त्रुटियों का समाधान मिला> = '0x110000', लेकिन आम सहमति थी कि वे निश्चित रूप से उन्हें नहीं चाहते थे। – SethMMorton

संबंधित मुद्दे