अगर एक स्ट्रिंग यूनिकोड या एससीआई है तो मैं कैसे जांच करूं?


271

पायथन में मुझे क्या करना है यह जानने के लिए कि एक स्ट्रिंग को एन्कोडिंग है?


56
यूनिकोड एक एनकोडिंग नहीं है
ulidtko

इससे भी महत्वपूर्ण बात, आपको क्यों परवाह करनी चाहिए?
जॉन्सवेब

@Johnsyweb के कारण{UnicodeDecodeError} 'ascii' codec can't decode byte 0xc2
एलेक्स

जवाबों:


295

पायथन 3 में, सभी तार यूनिकोड वर्णों के अनुक्रम हैं। एक bytesप्रकार है जो कच्चे बाइट्स रखता है।

पायथन 2 में, एक स्ट्रिंग प्रकार strया प्रकार का हो सकता है unicode। आप बता सकते हैं कि कौन सा कोड इस तरह से उपयोग कर रहा है:

def whatisthis(s):
    if isinstance(s, str):
        print "ordinary string"
    elif isinstance(s, unicode):
        print "unicode string"
    else:
        print "not a string"

यह "यूनिकोड या एएससीआईआई" में अंतर नहीं करता है; यह केवल पायथन प्रकारों को अलग करता है। एक यूनिकोड स्ट्रिंग में ASCII रेंज में विशुद्ध रूप से अक्षर शामिल हो सकते हैं, और एक बाईटस्ट्रिंग में ASCII, एनकोडेड यूनिकोड या यहां तक ​​कि गैर-पाठीय डेटा भी हो सकते हैं।


3
@ProsperousHeart: आप शायद Python 3 का उपयोग कर रहे हैं
ग्रेग हेविगिल

124

कैसे बताएं कि कोई वस्तु यूनिकोड स्ट्रिंग या बाइट स्ट्रिंग है

आप उपयोग कर सकते हैं typeया isinstance

पायथन 2 में:

>>> type(u'abc')  # Python 2 unicode string literal
<type 'unicode'>
>>> type('abc')   # Python 2 byte string literal
<type 'str'>

पायथन 2 में, strबाइट्स का सिर्फ एक क्रम है। अजगर को पता नहीं है कि इसकी एन्कोडिंग क्या है। unicodeप्रकार की दुकान पाठ करने के लिए सुरक्षित तरीका है। यदि आप इसे और अधिक समझना चाहते हैं, तो मैं http://farmdev.com/talks/unicode/ सुझाता हूं ।

पायथन 3 में:

>>> type('abc')   # Python 3 unicode string literal
<class 'str'>
>>> type(b'abc')  # Python 3 byte string literal
<class 'bytes'>

पायथन 3 में, strपायथन 2 की तरह है unicode, और इसका उपयोग पाठ को संग्रहीत करने के लिए किया जाता है। strपायथन 2 में क्या कहा गया था, इसे पायथन 3 में कहा जाता bytesहै।


कैसे बताएं कि क्या बाइट स्ट्रिंग वैध यूएफ -8 या एससीआई है

आप कॉल कर सकते हैं decode। यदि यह एक यूनिकोडडाउज़ररूट अपवाद को उठाता है, तो यह मान्य नहीं था।

>>> u_umlaut = b'\xc3\x9c'   # UTF-8 representation of the letter 'Ü'
>>> u_umlaut.decode('utf-8')
u'\xdc'
>>> u_umlaut.decode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

बस अन्य लोगों के संदर्भ के लिए - str.decode अजगर में मौजूद नहीं है। 3. ऐसा लगता है कि आपको unicode(s, "ascii")कुछ करना है या नहीं
शैडो

3
क्षमा करें, मेरा मतलब थाstr(s, "ascii")
छाया

1
यह अजगर 3 के लिए सटीक नहीं है
प्रोस्पेरस

2
@ProsperousHeart पाइथन को कवर करने के लिए अपडेट किया गया 3. और बायस्ट्रेस और यूनिक स्ट्रिंग्स के बीच के अंतर को समझाने की कोशिश करना।
मिकेल

44

अजगर 3.x में सभी तार यूनिकोड वर्णों के अनुक्रम हैं। और str के लिए आइंस्टीन जांच कर रहा है (जिसका अर्थ है डिफ़ॉल्ट रूप से यूनिकोड स्ट्रिंग) पर्याप्त होना चाहिए।

isinstance(x, str)

अजगर 2.x के संबंध में, अधिकांश लोग एक ऐसे कथन का उपयोग करते हुए प्रतीत होते हैं जिसमें दो चेक हैं। एक स्ट्रिंग के लिए और एक यूनिकोड के लिए।

यदि आप जांचना चाहते हैं कि क्या आपके पास एक कथन के साथ 'स्ट्रिंग जैसी' वस्तु है, तो आप निम्नलिखित कार्य कर सकते हैं:

isinstance(x, basestring)

यह गलत है। पायथन में 2.7 isinstance(u"x",basestring)रिटर्न True
पाइथननॉट

11
@PythonNut: मेरा मानना ​​है कि वह बिंदु था। ऊपर दिए गए अलग-अलग दोहरे परीक्षणों को बदलने के लिए आइंस्टीन (एक्स, बेसस्ट्रिंग) का उपयोग पर्याप्त है।
केक्यू।

5
यह कई मामलों में उपयोगी है, लेकिन जाहिर है कि प्रश्नकर्ता का मतलब क्या नहीं है।
mhsmith

3
यह सवाल का जवाब है। अन्य सभी ने गलत समझा कि ओपी ने क्या कहा और पायथन में टाइप चेकिंग के बारे में सामान्य उत्तर दिए।
fiatjaf

1
ओपी के सवाल का जवाब नहीं देता। प्रश्न का शीर्षक (अकेला) COULD की व्याख्या इस प्रकार की जानी चाहिए कि यह उत्तर सही हो। हालांकि, ओपी विशेष रूप से सवाल के विवरण में "यह पता लगाता है" जो कहते हैं, और इस जवाब से यह पता नहीं चलता है।
MD004

31

यूनिकोड एक कूटबन्धन नहीं है - कुमार मैकमिलन को उद्धृत करने के लिए:

यदि ASCII, UTF-8, और अन्य बाइट स्ट्रिंग्स "टेक्स्ट" हैं ...

... तो यूनिकोड "टेक्स्ट-नेस" है;

यह पाठ का सार रूप है

मैकमिलन के यूनिकोड इन पाइथन, पाइकॉन 2008 से पूरी तरह से डिम्टिफाइड बात के बारे में पढ़ा है , यह स्टैक ओवरफ्लो पर संबंधित जवाबों की तुलना में चीजों को बहुत बेहतर बताता है।


उन स्लाइडों में शायद यूनिकोड का सबसे अच्छा परिचय है जो मैं आज तक आया हूं
जॉनी

23

यदि आपके कोड को Python 2 और Python 3 दोनों के साथ संगत होने की आवश्यकता है , तो आप चीज़ों को सीधे isinstance(s,bytes)या isinstance(s,unicode)बिना लपेटे उपयोग नहीं कर सकते हैं या तो प्रयास करें / छोड़कर या एक अजगर संस्करण परीक्षण करें, क्योंकि bytesPython 2 unicodeमें अपरिभाषित है और Python 3 में अपरिभाषित है ।

कुछ बदसूरत workarounds हैं। एक बहुत ही बदसूरत एक प्रकार के नाम की तुलना करने के बजाय खुद की तुलना करना है। यहाँ एक उदाहरण है:

# convert bytes (python 3) or unicode (python 2) to str
if str(type(s)) == "<class 'bytes'>":
    # only possible in Python 3
    s = s.decode('ascii')  # or  s = str(s)[2:-1]
elif str(type(s)) == "<type 'unicode'>":
    # only possible in Python 2
    s = str(s)

यकीनन थोड़ा कम बदसूरत वर्कअराउंड पायथन संस्करण संख्या की जांच करना है, जैसे:

if sys.version_info >= (3,0,0):
    # for Python 3
    if isinstance(s, bytes):
        s = s.decode('ascii')  # or  s = str(s)[2:-1]
else:
    # for Python 2
    if isinstance(s, unicode):
        s = str(s)

उन दोनों unpythonic हैं, और ज्यादातर समय वहाँ शायद एक बेहतर तरीका है।


6
बेहतर तरीका शायद उपयोग करना है six, और इसके खिलाफ परीक्षण करना है six.binary_typeऔरsix.text_type
इयान क्लैलैंड

1
आप टाइप नामों की जांच के लिए टाइप (ओं) .__ name__ का उपयोग कर सकते हैं ।
पाउलो फ्रीटास

जब तक कोई तर्क त्रुटि न हो, मैं उस बिट कोड के लिए उपयोग के मामले में निश्चित नहीं हूं। मुझे लगता है कि अजगर 2 कोड में "नहीं" होना चाहिए। अन्यथा आप पायथन 3 के लिए सब कुछ यूनिकोड स्ट्रिंग्स में परिवर्तित कर रहे हैं और पायथन 2 के लिए विपरीत है!
ऑलिगॉफ्रेन

हां, ऑलिगॉफ्रेन, यही वह करता है। मानक आंतरिक तार अजगर 3 में यूनिकोड और पायथन 2 में एएससीआईआई हैं। इसलिए कोड स्निपेट टेक्स्ट को मानक आंतरिक स्ट्रिंग प्रकार (यूनिकोड या एएससीआईआई हो) में परिवर्तित करते हैं।
डेव बर्टन

12

उपयोग:

import six
if isinstance(obj, six.text_type)

छह पुस्तकालय के अंदर इसे निम्न रूप में दर्शाया गया है:

if PY3:
    string_types = str,
else:
    string_types = basestring,

2
यह होना चाहिए if isinstance(obj, six.text_type) । लेकिन हाँ यह सही उत्तर है।
कारंतन

ओपी के सवाल का जवाब नहीं देता। प्रश्न का शीर्षक (अकेला) COULD की व्याख्या इस प्रकार की जानी चाहिए कि यह उत्तर सही हो। हालांकि, ओपी विशेष रूप से सवाल के विवरण में "यह पता लगाता है" जो कहते हैं, और इस जवाब से यह पता नहीं चलता है।
MD004

4

ध्यान दें कि पायथन 3 पर, वास्तव में यह कहना उचित नहीं है:

  • strs किसी भी x के लिए UTFx हैं (उदा। UTF8)

  • strs यूनिकोड हैं

  • strs को यूनिकोड वर्णों के संग्रह का आदेश दिया गया है

पायथन का strप्रकार (सामान्य रूप से) यूनिकोड कोड बिंदुओं का एक क्रम है, जिसमें से कुछ नक्शे पात्रों के हैं।


पायथन 3 पर भी, इस प्रश्न का उत्तर देना इतना आसान नहीं है जितना आप कल्पना कर सकते हैं।

ASCII- संगत स्ट्रिंग्स के लिए परीक्षण करने का एक स्पष्ट तरीका एक प्रयास एनकोड है:

"Hello there!".encode("ascii")
#>>> b'Hello there!'

"Hello there... ☃!".encode("ascii")
#>>> Traceback (most recent call last):
#>>>   File "", line 4, in <module>
#>>> UnicodeEncodeError: 'ascii' codec can't encode character '\u2603' in position 15: ordinal not in range(128)

त्रुटि मामलों को अलग करती है।

पायथन 3 में, कुछ ऐसे तार भी हैं जिनमें अमान्य यूनिकोड कोड बिंदु हैं:

"Hello there!".encode("utf8")
#>>> b'Hello there!'

"\udcc3".encode("utf8")
#>>> Traceback (most recent call last):
#>>>   File "", line 19, in <module>
#>>> UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 0: surrogates not allowed

उन्हें भेद करने के लिए एक ही विधि का उपयोग किया जाता है।


3

यह किसी और की मदद कर सकता है, मैंने वेरिएबल एस के स्ट्रिंग प्रकार के लिए परीक्षण शुरू कर दिया, लेकिन मेरे आवेदन के लिए, इसे केवल utf-8 के रूप में वापस करने के लिए अधिक समझ में आया। Return_utf को कॉल करने वाली प्रक्रिया, फिर जानता है कि यह किसके साथ काम कर रहा है और स्ट्रिंग को उचित तरीके से संभाल सकता है। कोड प्राचीन नहीं है, लेकिन मैं इसके लिए संस्करण परीक्षण के बिना पायथन संस्करण अज्ञेयवादी या छह आयात करने का इरादा रखता हूं। अन्य लोगों की मदद करने के लिए कृपया नीचे दिए गए नमूना कोड में सुधार के साथ टिप्पणी करें।

def return_utf(s):
    if isinstance(s, str):
        return s.encode('utf-8')
    if isinstance(s, (int, float, complex)):
        return str(s).encode('utf-8')
    try:
        return s.encode('utf-8')
    except TypeError:
        try:
            return str(s).encode('utf-8')
        except AttributeError:
            return s
    except AttributeError:
        return s
    return s # assume it was already utf-8

आप मेरे मित्र सही प्रतिक्रिया के पात्र हैं! मैं अजगर 3 का उपयोग कर रहा हूँ और मुझे तब भी समस्या हो रही थी जब तक मुझे यह खजाना नहीं मिल गया!
15:15 बजे mnsr

2

आप यूनिवर्सल एनकोडिंग डिटेक्टर का उपयोग कर सकते हैं , लेकिन इस बात से अवगत रहें कि यह आपको वास्तविक अनुमान नहीं बल्कि सर्वश्रेष्ठ अनुमान देगा, क्योंकि उदाहरण के लिए एक स्ट्रिंग "एबीसी" के एन्कोडिंग को जानना असंभव है। आपको कहीं और एन्कोडिंग जानकारी प्राप्त करने की आवश्यकता होगी, उदाहरण के लिए HTTP प्रोटोकॉल उस के लिए सामग्री-प्रकार हेडर का उपयोग करता है।



0

एक सरल दृष्टिकोण यह जांचना है कि unicodeक्या एक बिलिन फ़ंक्शन है। यदि हां, तो आप पायथन 2 में हैं और आपकी स्ट्रिंग एक स्ट्रिंग होगी। यह सुनिश्चित करने के लिए कि सब कुछ एक में unicodeहो सकता है:

import builtins

i = 'cats'
if 'unicode' in dir(builtins):     # True in python 2, False in 3
  i = unicode(i)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.