पायथन 2.6 में यूनिकोड_लिटरल्स का उपयोग करते हुए कोई भी गोच?


101

हमने पहले ही पायथन 2.6 के तहत चल रहे हमारे कोड बेस को प्राप्त कर लिया है। पायथन 3.0 की तैयारी के लिए, हमने जोड़ना शुरू कर दिया है:

__future__ से यूनिकोड_लिटरल्स आयात करें

हमारी .pyफाइलों में (जैसा कि हम उन्हें संशोधित करते हैं)। मैं सोच रहा था कि क्या कोई और ऐसा कर रहा है और किसी भी गैर-स्पष्ट गोचरों में चला गया है (शायद बहुत समय डिबगिंग खर्च करने के बाद)।

जवाबों:


101

जब मैंने यूनिकोड स्ट्रिंग्स के साथ काम किया है, तो समस्याओं का मुख्य स्रोत यूनिकोड के साथ यूटीएफ -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
मैं या decode()समाधानों के बजाय समाधानों के साथ जाने का सुझाव दूंगा: जितनी बार आप यूनिकोड ऑब्जेक्ट्स का उपयोग करते हैं, कोड उतना ही स्पष्ट होता है, क्योंकि आप जो चाहते हैं वह वर्णों के तारों में हेरफेर करना है, न कि बाहरी बाइट्स के साथ बाइट्स के एक बाहरी रूप से निहित एन्कोडिंग। str()encode()
एरिक ओ लेबिगॉट

8
कृपया अपनी शब्दावली ठीक करें। when you mix utf-8 encoded strings with unicode onesUTF-8 और यूनिकोड नहीं 2 अलग अलग एनकोडिंग; यूनिकोड एक मानक है और UTF-8 एक एनकोडिंग है जो इसे परिभाषित करता है।
कोस

11
@Kos: मुझे लगता है कि वह यूनिकोड (इसलिए डिकोडेड) वस्तुओं के साथ "utf-8 एन्कोडेड स्ट्रिंग्स" वस्तुओं का मिश्रण करता है । पूर्व प्रकार का है , बाद वाला प्रकार है । अलग-अलग ऑब्जेक्ट होने के कारण, समस्या उत्पन्न हो सकती है यदि आप उन्हें strunicode
समाप्‍त

क्या यह लागू होता है python>=2.6या python==2.6?
जौहर १५'१३

16

इसके अलावा 2.6 में (अजगर 2.6.5 RC1 + से पहले) यूनिकोड शाब्दिक कीवर्ड तर्क के साथ अच्छा नहीं खेलता है ( जारी अंक 7878 :

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

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

17
सिर्फ FYI करें, अजगर 2.6.5 RC1 + ने यह तय किया है।
महमूद अब्देलकादर

13

मैंने पाया कि यदि आप unicode_literalsनिर्देश जोड़ते हैं तो आपको भी कुछ जोड़ना चाहिए:

 # -*- coding: utf-8

पहली या दूसरी पंक्ति में आपकी .py फ़ाइल। अन्यथा लाइनें जैसे:

 foo = "barré"

इस तरह एक त्रुटि के परिणामस्वरूप:

SyntaxError: गैर-ASCII वर्ण '\ xc3' फ़ाइल mumble.py पर लाइन 198 में,
 लेकिन कोई एन्कोडिंग घोषित नहीं किया गया; http://www.python.org/peps/pep-0263.html देखें
 ब्योरा हेतु

5
@IanMackinnon: पायथन 3 मानता है कि फाइलें डिफ़ॉल्ट रूप से UTF8 हैं
एंडोलिथ

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

-*-की आवश्यकता नहीं है; यदि आप emacs- संगत तरीके के लिए जा रहे थे, तो मुझे लगता है कि आपको आवश्यकता होगी -*- encoding: utf-8 -*-( -*-अंत में भी देखें)। आप सभी की जरूरत है coding: utf-8(या के =बजाय भी : )।
क्रिस मॉर्गन

2
आपको यह त्रुटि मिलती है या नहीं from __future__ import unicode_literals
फ्लिम

3
एमएसीएस संगतता के लिए # -*- coding: utf-8 -*- "कोडिंग" ("एन्कोडिंग" या "फाइलकोडिंग" या कुछ और नहीं - पायथन सिर्फ किसी भी उपसर्ग की परवाह किए बिना "कोडिंग" की तलाश करता है) की आवश्यकता होती है।
एलेक्स डुपॉय

7

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

आदर्श रूप से, निम्न कोड एक अक्रियार्थक होगा, जो हमेशा unicode_literalsऔर पायथन {2.7, 3.50} उपयोग के सभी संयोजनों के लिए काम करना चाहिए :

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+

दूसरा जोर काम करने के लिए होता है, क्योंकि पायथन 2.7 में repr('\xa4')मूल्यांकन करता है u'\xa4'


2
मुझे लगता है कि यहाँ बड़ी समस्या यह है कि आप reprकिसी वस्तु को पुनः प्राप्त करने के लिए उपयोग कर रहे हैं । reprप्रलेखन स्पष्ट रूप से कहा गया है कि यह है नहीं एक आवश्यकता। मेरी राय में, यह reprकेवल डीबगिंग के लिए कुछ उपयोगी है।
jpmc26

5

और भी हैं।

ऐसे पुस्तकालय और भवन हैं जो स्ट्रिंग की अपेक्षा करते हैं जो यूनिकोड को सहन नहीं करते हैं।

दो उदाहरण:

निर्मित:

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

(थोड़ा एसेटिक) यूनिकोड_लिटरल्स के साथ काम नहीं करता है: टाइप () एक स्ट्रिंग की अपेक्षा करता है।

पुस्तकालय:

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
और प्रकार सामान भी metaclasses में लीक - तो Django में किसी भी तार आप में घोषित class Meta:किया जाना चाहिएb'field_name'
हामिश डाउनर

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

0

यदि from __future__ import unicode_literalsआपके द्वारा उपयोग किए गए किसी भी मॉड्यूल को आयात किया गया है तो क्लिक पूरे स्थान पर यूनिकोड अपवादों को बढ़ाएगाclick.echo । यह एक दुःस्वप्न है…

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.