2009-05-01 13 views
95

हम पहले से ही हमारे कोड बेस पाइथन 2.6 के तहत चल रहे हैं।Python 2.6 में यूनिकोड_लिटरल्स का उपयोग कर कोई भी गॉचास?

 
from __future__ import unicode_literals 
हमारे .py फाइलों में

(हम उन्हें संशोधित रूप में): आदेश पायथन 3.0 के लिए तैयार करने के लिए हमें जोड़ने शुरू कर दिया है। मैं सोच रहा हूं कि कोई और ऐसा कर रहा है और किसी भी गैर-स्पष्ट गॉथस में चला गया है (शायद बहुत समय व्यतीत करने के बाद)।

# -*- coding: utf-8 
पहली या दूसरी पंक्ति अपने .py फ़ाइल को

:

उत्तर

99

समस्याओं मैं यूनिकोड तार के साथ काम किया है का मुख्य स्रोत है जब आप utf-8 के साथ इनकोडिंग तार मिश्रण यूनिकोड वाले।

उदाहरण के लिए, निम्न स्क्रिप्ट पर विचार करें।

two.py

# encoding: utf-8 
name = 'helló wörld from two' 

one.py

# encoding: utf-8 
from __future__ import unicode_literals 
import two 
name = 'helló wörld from one' 
print name + two.name 

python one.py चलाने का उत्पादन होता है:

Traceback (most recent call last): 
    File "one.py", line 5, in <module> 
    print name + two.name 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128) 

इस उदाहरण में, two.name एक UTF-8 एन्कोडेड स्ट्रिंग है (यूनिकोड नहीं) क्योंकि यह unicode_literals आयात नहीं करता था, और one.name एक यूनिकोड स्ट्रिंग है। जब आप दोनों मिश्रण करते हैं, तो पाइथन एन्कोडेड स्ट्रिंग को डीकोड करने की कोशिश करता है (यह एसीआईआई मानता है) और इसे यूनिकोड में परिवर्तित करता है और विफल रहता है। यह काम करेगा यदि आपने print name + two.name.decode('utf-8') किया था।

यदि आप स्ट्रिंग को एन्कोड करते हैं और बाद में उन्हें मिश्रण करने का प्रयास करते हैं तो वही बात हो सकती है। उदाहरण के लिए, इस काम करता है:

# encoding: utf-8 
html = '<html><body>helló wörld</body></html>' 
if isinstance(html, unicode): 
    html = html.encode('utf-8') 
print 'DEBUG: %s' % html 

आउटपुट:

DEBUG: <html><body>helló wörld</body></html> 

लेकिन import unicode_literals जोड़ने यह नहीं है के बाद:

# encoding: utf-8 
from __future__ import unicode_literals 
html = '<html><body>helló wörld</body></html>' 
if isinstance(html, unicode): 
    html = html.encode('utf-8') 
print 'DEBUG: %s' % html 

आउटपुट:

Traceback (most recent call last): 
    File "test.py", line 6, in <module> 
    print 'DEBUG: %s' % html 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128) 

यह विफल रहता है क्योंकि 'DEBUG: %s' एक यूनिकोड स्ट्रिंग है और इसलिए पायथन html को डीकोड करने का प्रयास करता है। प्रिंट को ठीक करने के कुछ तरीके या तो print str('DEBUG: %s') % html या print 'DEBUG: %s' % html.decode('utf-8') कर रहे हैं।

मुझे उम्मीद है कि यह यूनिकोड स्ट्रिंग का उपयोग करते समय संभावित गॉथस को समझने में आपकी सहायता करेगा।

+11

मैं 'str()' या 'एन्कोड() 'समाधानों के बजाय' डीकोड() 'समाधान के साथ जाने का सुझाव दूंगा: जितनी बार आप यूनिकोड ऑब्जेक्ट्स का उपयोग करते हैं, उतना स्पष्ट कोड है, क्योंकि आप जो चाहते हैं एक बाहरी रूप से निहित एन्कोडिंग के साथ बाइट्स के सरणी नहीं, वर्णों के तारों का उपयोग करें। – EOL

+7

कृपया अपनी शब्दावली को ठीक करें।'जब आप यूटीएफ -8 एन्कोडेड तारों को यूनिकोड वाले यूटीएफ -8 के साथ मिश्रित करते हैं और यूनिकोड 2 अलग-अलग एन्कोडिंग नहीं करते हैं; यूनिकोड एक मानक है और यूटीएफ -8 एन्कोडिंग में से एक है जो इसे परिभाषित करता है। – Kos

+10

@ कोस: मुझे लगता है कि उसका मतलब है "यूटीएफ -8 एन्कोडेड स्ट्रिंग्स" * ऑब्जेक्ट्स * यूनिकोड (इसलिए डीकोडेड) * ऑब्जेक्ट्स * के साथ। पूर्व प्रकार 'str' प्रकार है, बाद वाला प्रकार' यूनिकोड 'है। विभिन्न ऑब्जेक्ट्स होने के नाते, यदि आप – MestreLion

13

मुझे लगता है कि अगर आप unicode_literals निर्देश जोड़ने आप भी तरह कुछ जोड़ना चाहिए मिला। अन्यथा इस तरह के रूप लाइनों: में

foo = "barré" 

परिणाम एक एक त्रुटि जैसे:

 
SyntaxError: Non-ASCII character '\xc3' in file mumble.py on line 198, 
but no encoding declared; see http://www.python.org/peps/pep-0263.html 
for details 
+5

+1। हालांकि आप इसे * सभी * परिस्थितियों में नहीं करना चाहिए? –

+5

@IanMackinnon: पायथन 3 मानता है कि फाइलें – endolith

+3

@endolith द्वारा यूटीएफ 8 हैं: लेकिन पायथन 2 नहीं है, और यदि आप गैर-असीसी अक्षर * टिप्पणियों में भी उपयोग करते हैं तो यह वाक्यविन्यास त्रुटि देगा! तो IMHO '# - * - कोडिंग: utf-8' एक वर्चुअल अनिवार्य कथन है, भले ही आप 'यूनिकोड_लिटरल्स' का उपयोग करें या – MestreLion

16

2.6 में भी (पायथन 2.6 से पहले।5 RC1 +) यूनिकोड शाब्दिक कीवर्ड तर्कों (issue4978) के साथ अच्छा नहीं चलता है:

उदाहरण के लिए निम्नलिखित कोड unicode_literals बिना काम करता है, लेकिन लेखन त्रुटि के साथ विफल: keywords must be string अगर unicode_literals प्रयोग किया जाता है।

>>> def foo(a=None): pass 
    ... 
    >>> foo(**{'a':1}) 
    Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
     TypeError: foo() keywords must be strings 
+16

बस एफवाईआई, पायथन 2.6.5 आरसी 1 + ने इसे ठीक कर दिया है। –

8

भी खाते है कि unicode_literaleval() नहीं बल्कि repr() (एक असममित व्यवहार जो imho एक बग है) को प्रभावित करेगा में रखना है, यानी eval(repr(b'\xa4'))b'\xa4' के बराबर नहीं होगा (के रूप में यह अजगर 3 के साथ होता है)। ,

from __future__ import unicode_literals 

bstr = b'\xa4' 
assert eval(repr(bstr)) == bstr # fails in Python 2.7, holds in 3.1+ 

ustr = '\xa4' 
assert eval(repr(ustr)) == ustr # holds in Python 2.7 and 3.1+ 

दूसरा अभिकथन काम करने के लिए होता है के बाद से:

आदर्श रूप में, निम्नलिखित कोड एक अपरिवर्तनीय है, जो हमेशा काम करना चाहिए, unicode_literals और अजगर {2.7, 3.x} उपयोग के सभी संयोजनों के लिए होगा repr('\xa4') पायथन 2.7 में u'\xa4' का मूल्यांकन करता है।

+1

मुझे लगता है कि यहां बड़ी समस्या यह है कि आप किसी ऑब्जेक्ट को पुन: उत्पन्न करने के लिए 'repr' का उपयोग कर रहे हैं। ['Repr' दस्तावेज़ीकरण] (https://docs.python.org/2/library/functions.html#func-repr) स्पष्ट रूप से बताता है कि यह * आवश्यकता * नहीं है। मेरी राय में, यह केवल डीबगिंग के लिए उपयोगी कुछ चीज़ों के लिए 'repr' relegates। – jpmc26

5

और भी कुछ हैं।

पुस्तकालयों और बिल्टिन हैं जो तारों की अपेक्षा करते हैं जो यूनिकोड को बर्दाश्त नहीं करते हैं।

दो उदाहरण:

निर्मित:

myenum = type('Enum',(), enum) 

(थोड़ा esotic) unicode_literals साथ काम नहीं करता: प्रकार() एक स्ट्रिंग की उम्मीद है।

पुस्तकालय:

from wx.lib.pubsub import pub 
pub.sendMessage("LOG MESSAGE", msg="no go for unicode literals") 

काम नहीं करता: wx pubsub पुस्तकालय एक स्ट्रिंग संदेश प्रकार की उम्मीद है।

पूर्व गूढ़ और आसानी से

myenum = type(b'Enum',(), enum) 

साथ तय हो गई है लेकिन बाद यदि आपका कोड pub.sendMessage() (जो मेरा है) करने के लिए कॉल से भरा हुआ है विनाशकारी है।

डैंग, एह?!?

+3

और टाइप चीजें मेटाक्लास में भी लीक होती हैं - इसलिए डैंजो में आप किसी भी स्ट्रिंग को 'क्लास मेटा' में घोषित करते हैं: '' b'field_name'' –

+2

हाँ होना चाहिए ... मेरे मामले में मुझे एहसास हुआ कि यह खोज करने के प्रयास के लायक था और बी 'संस्करणों के साथ सभी sendMessage तारों को प्रतिस्थापित करें। यदि आप ड्रेडेड "डिकोड" अपवाद से बचना चाहते हैं, तो आपके प्रोग्राम में यूनिकोड का सख्ती से उपयोग करने, इनपुट और आउटपुट को आवश्यक रूप से परिवर्तित करने जैसी कुछ भी नहीं है ("यूनिकोड सैंडविच" जिसे मैंने इस विषय पर पढ़े गए कुछ पेपर में संदर्भित किया है)। कुल मिलाकर, यूनिकोड_लिटरल्स मेरे लिए बड़ी जीत रही है ... – GreenAsJade

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