हमें py स्क्रिप्ट में sys.setdefaultencoding ("utf-8") का उपयोग क्यों नहीं करना चाहिए?


166

मैंने कुछ py स्क्रिप्ट देखी हैं जो स्क्रिप्ट के शीर्ष पर इसका उपयोग करती हैं। किन मामलों में इसका उपयोग करना चाहिए?

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

2
वहाँ IPython में इस का उपयोग कर के साथ एक समस्या है,% समय कार्य करना बंद कर github.com/ipython/ipython/issues/8071
seanv507

3
@ seanv507, जवाब पढ़ें - इसका उपयोग करने पर गंभीरता से हतोत्साहित किया जाता है
एलेस्टेयर मैककॉर्मैक


2
यह कैसे sys.setdefaultencoding ('utf-8') के खतरों का सटीक डुप्लिकेट नहीं है ? हालांकि यह (2010) पूछ रहा है कि एक (2015) भविष्यवाणी करता है? लेकिन उस पूछने के अच्छे जवाब भी हैं। क्या करें? इसके अलावा, स्पष्ट होने के लिए, यह प्रश्न केवल पायथन 2 नहीं 3 पर समझ में आता है, फिर भी यह कहीं भी टैग या उल्लेख नहीं किया गया है।
22

SO उत्तरों में गोता लगाने
ccpizza

जवाबों:


141

दस्तावेज़ीकरण के अनुसार: यह आपको डिफ़ॉल्ट ASCII से दूसरे एन्कोडिंग जैसे UTF-8 पर स्विच करने की अनुमति देता है, जिसे पायथन रनटाइम का उपयोग करेगा जब भी इसे यूनिकोड के लिए एक स्ट्रिंग बफर को डीकोड करना होगा।

यह फ़ंक्शन केवल पायथन स्टार्ट-अप समय पर उपलब्ध है, जब पायथन पर्यावरण को स्कैन करता है। इसे सिस्टम-वाइड मॉड्यूल में बुलाया जाना है sitecustomize.py, इस मॉड्यूल का मूल्यांकन होने के बाद, setdefaultencoding()फ़ंक्शन sysमॉड्यूल से हटा दिया जाता है ।

वास्तव में इसका उपयोग करने का एकमात्र तरीका एक पुनः लोड हैक के साथ है जो विशेषता को वापस लाता है।

इसके अलावा, के उपयोग sys.setdefaultencoding()को हमेशा हतोत्साहित किया गया है , और यह py3k में एक नो-ऑप बन गया है। Py3k की एन्कोडिंग "utf-8" के लिए हार्ड-वायर्ड है और इसे बदलने से त्रुटि उत्पन्न होती है।

मैं पढ़ने के लिए कुछ संकेत देता हूं:


6
महान सामान, हालांकि यहां बहुत अधिक जानकारी से मृत्यु का एक सा है। मैं सबसे सिर्फ इस लेख पर ध्यान केंद्रित कर सीखा: blog.notdot.net/2010/07/Getting-unicode-right-in-Python
MBB

3
मैं जोड़ना चाहूंगा कि डिफ़ॉल्ट एन्कोडिंग का उपयोग एन्कोडिंग के लिए भी किया जाता है ( जब यह एन्कोडिंग के लिए लिखना है , जैसे कि पायथन प्रोग्राम के आउटपुट को रीडायरेक्ट करते समय)। sys.stdoutNone
एरिक ओ लेबिगॉट

14
+1 के लिए " sys.setdefaultencoding()हमेशा के लिए उपयोग को हतोत्साहित किया गया"
jfs

7
'हार्ड-वायर्ड टू यूटीएफ -8' सच नहीं है, यह हार्डवेर नहीं है और यह हमेशा नहीं होता है UTF-8LC_ALL=en_US.UTF-8 python3 -c 'import sys; print(sys.stdout.encoding)'देता है, UTF-8लेकिन LC_ALL=C python3 -c 'import sys; print(sys.stdout.encoding)'देता है ANSI_X3.4-1968(या शायद कुछ और)
टीनो

7
@Tino, कंसोल एन्कोडिंग डिफ़ॉल्ट एन्कोडिंग के लिए अलग है।
एलेस्टेयर मैककॉर्मैक

59

tl; डॉ

जवाब है कभी ! (जब तक आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं)

9/10 बार समाधान को एन्कोडिंग / डिकोडिंग की उचित समझ के साथ हल किया जा सकता है।

1/10 लोगों के पास गलत तरीके से परिभाषित स्थान या वातावरण है और उन्हें सेट करने की आवश्यकता है:

PYTHONIOENCODING="UTF-8"  

कंसोल मुद्रण समस्याओं को ठीक करने के लिए उनके वातावरण में।

यह क्या करता है?

sys.setdefaultencoding("utf-8")(पुनः उपयोग से बचने के लिए मारा गया) जब भी पाइथन 2.x को यूनिकोड () को एक स्ट्रेट () और (इसके विपरीत) में परिवर्तित करने की आवश्यकता होती है, तो डिफ़ॉल्ट डिफ़ॉल्ट एन्कोडिंग / डिकोडिंग में परिवर्तन होता है और एन्कोडिंग नहीं दी जाती है। अर्थात:

str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC") 

पायथन 2.x में, डिफ़ॉल्ट एन्कोडिंग ASCII पर सेट है और उपरोक्त उदाहरण इसके साथ विफल होंगे:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)

(मेरा कंसोल UTF-8 के रूप में कॉन्फ़िगर किया गया है, इसलिए "€" = '\xe2\x82\xac', इस पर अपवाद \xe2)

या

UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)

sys.setdefaultencoding("utf-8")मुझे मेरे लिए काम करने की अनुमति देगा , लेकिन जरूरी नहीं कि उन लोगों के लिए काम करें जो UTF-8 का उपयोग नहीं करते हैं। ASCII का डिफ़ॉल्ट यह सुनिश्चित करता है कि एन्कोडिंग की मान्यताओं को कोड में बेक नहीं किया गया है

कंसोल

sys.setdefaultencoding("utf-8")ठीक करने के लिए प्रदर्शित होने का एक साइड इफेक्ट भी है sys.stdout.encoding, जो कंसोल में वर्णों को प्रिंट करते समय उपयोग किया जाता है। इसे सेट करने के लिए पायथन उपयोगकर्ता के लोकेल (लिनक्स / OS X / Un * x) या कोडपेज (विंडोज) का उपयोग करता है। कभी-कभी, उपयोगकर्ता का स्थान टूट जाता है और बस कंसोल एन्कोडिंगPYTHONIOENCODING को ठीक करने की आवश्यकता होती है ।

उदाहरण:

$ export LANG=en_GB.gibberish
$ python
>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>> print u"\u20AC"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
>>> exit()

$ PYTHONIOENCODING=UTF-8 python
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print u"\u20AC"
€

Sys.setdefaultencoding ("utf-8") के साथ इतना बुरा क्या है ?

लोग 16 साल से पायथन 2.x के खिलाफ इस समझ के साथ विकसित हो रहे हैं कि डिफ़ॉल्ट एन्कोडिंग ASCII है। UnicodeErrorगैर-ASCII में पाए जाने वाले तार पर यूनिकोड रूपांतरण के लिए स्ट्रिंग को संभालने के लिए अपवाद हैंडलिंग तरीके लिखे गए हैं।

से https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/

def welcome_message(byte_string):
    try:
        return u"%s runs your business" % byte_string
    except UnicodeError:
        return u"%s runs your business" % unicode(byte_string,
            encoding=detect_encoding(byte_string))

print(welcome_message(u"Angstrom (Å®)".encode("latin-1"))

डिफ़ॉल्ट कोडिंग को सेट करने से पहले यह कोड एससीआई एन्कोडिंग में "in" को डिकोड करने में असमर्थ होगा और फिर एन्कोडिंग का अनुमान लगाने के लिए अपवाद हैंडलर में प्रवेश करेगा और इसे ठीक से यूनिकोड में बदल देगा। मुद्रण: Angstrom ()®) आपका व्यवसाय चलाता है। एक बार जब आप डिफेंककोडिंग को utf-8 में सेट करते हैं, तो कोड यह पाएगा कि बाइट_स्ट्रिंग को utf-8 के रूप में व्याख्या किया जा सकता है और इसलिए यह डेटा को मैन्गल करेगा और इसके बजाय इसे लौटाएगा: Angstrom (Ů) आपका व्यवसाय चलाता है।

जो कुछ स्थिर होना चाहिए उसे बदलने से आपके द्वारा निर्भर मॉड्यूल पर नाटकीय प्रभाव पड़ेगा। अपने कोड के अंदर और बाहर आने वाले डेटा को ठीक करना बेहतर है।

उदाहरण की समस्या

जबकि डिफ़ॉल्ट उदाहरण के लिए UTF-8 की सेटिंग निम्नलिखित उदाहरण में मूल कारण नहीं है, यह दिखाता है कि कैसे समस्याएँ मुखौटा होती हैं और कैसे, जब इनपुट एन्कोडिंग में परिवर्तन होता है, तो कोड एक स्पष्ट तरीके से टूट जाता है: यूनिकोडडबलक्रेडर: utf8 'कोडेक स्थिति 3131 में 0 डेक्स बाइट 0x80: अमान्य प्रारंभ बाइट


2
जबकि इसमें आश्चर्य की बात है sys.setdefaultencoding("utf-8"), कोड को पायथन 3 की तरह व्यवहार करना अच्छा है। यह अब 2017 है। यहां तक ​​कि जब आपने 2015 में जवाब वापस लिखा था, तो मुझे लगता है कि पिछड़े के बजाय आगे देखना बेहतर था। यह वास्तव में मेरे लिए सबसे सरल समाधान था, जब मैंने पाया कि मेरा कोड पायथन 2 में अलग तरह से व्यवहार करता है, इस पर निर्भर करता है कि आउटपुट पुनर्निर्देशित है (पायथन 2 के लिए बहुत बुरा समस्या)। कहने की जरूरत नहीं है, मेरे पास पहले से ही है # coding: utf-8, और मुझे पायथन 3 के लिए किसी भी वर्कअराउंड की आवश्यकता नहीं है (मुझे वास्तव में setdefaultencodingउपयोग किए गए संस्करण की जांच करना है)।
योंगवेई वू

यह बहुत अच्छा है और यह आपके लिए काम करता है लेकिन sys.setdefaultencoding("utf-8")आपके Py 2.x कोड को Python 3 के साथ संगत नहीं बनाता है। न ही यह बाहरी मॉड्यूल को ठीक करता है जो मान लेता है कि डिफ़ॉल्ट एन्कोडिंग ASCII है। अपने कोड पायथन 3 को संगत बनाना बहुत आसान है और इसके लिए इस नॉटी हैक की आवश्यकता नहीं होती है। उदाहरण के लिए यह बहुत ही वास्तविक समस्याएँ क्यों पैदा करता है, इस धारणा के साथ अमेज़ॅन के साथ मेरा अनुभव देखें: stackoverflow.com/questions/39465220/…
एलेस्टेयर मैककॉर्मैक

1
@AlastairMcCormack आप रॉक करते हैं, मेरी साइट महीनों से है और यह पता नहीं लगा सकी कि क्या करना है। अंत में, PYTHONIOENCODING="UTF-8"मेरे Python2.7 Django-1.11 पर्यावरण की मदद की। धन्यवाद।
सैम

मुझे पता है कि आपने उदाहरण की नकल की है, लेकिन मुझे पता है कि पैकेज क्या है detect_encoding
dlamblin

@dlamblin कोड उदाहरण उद्धरण को प्रमाणित करने के लिए है और इसे आपके कोड में उपयोग नहीं किया जाना चाहिए। कल्पना कीजिए कि detect_encodingएक ऐसी विधि है जो भाषा के सुराग के आधार पर एक स्ट्रिंग के एन्कोडिंग का पता लगा सकती है।
एलिस्टर मैककॉर्मैक

18
#!/usr/bin/env python
#-*- coding: utf-8 -*-
u = u'moçambique'
print u.encode("utf-8")
print u

chmod +x test.py
./test.py
moçambique
moçambique

./test.py > output.txt
Traceback (most recent call last):
  File "./test.py", line 5, in <module>
    print u
UnicodeEncodeError: 'ascii' codec can't encode character 
u'\xe7' in position 2: ordinal not in range(128)

शेल काम करता है, sdtout को नहीं भेज रहा है, ताकि एक वर्कअराउंड हो, stdout को लिखने के लिए।

मैंने अन्य दृष्टिकोण बनाया, जो sys.stdout.encoding परिभाषित नहीं होने पर या अन्य शब्दों में, चलाया नहीं जाता है, तो निर्यात करने के लिए लिखने के लिए पहले PYTHONIOENCODING = UTF-8 को निर्यात की आवश्यकता है।

import sys
if (sys.stdout.encoding is None):            
    print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout." 
    exit(1)


इसलिए, एक ही उदाहरण का उपयोग कर:

export PYTHONIOENCODING=UTF-8
./test.py > output.txt

काम करेगा


3
यह पूछे गए प्रश्न का उत्तर नहीं देता है। बल्कि विषय पर कुछ मूर्त विचार।
ivan_pozdeev

3
  • पहला खतरा भीतर है reload(sys)

    जब आप किसी मॉड्यूल को पुनः लोड करते हैं, तो आप वास्तव में अपने रनटाइम में मॉड्यूल की दो प्रतियां प्राप्त करते हैं। पुराना मॉड्यूल सब कुछ की तरह एक पायथन ऑब्जेक्ट है, और जब तक इसके संदर्भ हैं तब तक जीवित रहता है। तो, आधी वस्तुएं पुराने मॉड्यूल की ओर इशारा करती हैं, और आधी नई की ओर। जब आप कुछ बदलाव करते हैं, तो आप इसे कभी नहीं देखेंगे जब कोई यादृच्छिक वस्तु परिवर्तन नहीं देखती है:

    (This is IPython shell)
    
    In [1]: import sys
    
    In [2]: sys.stdout
    Out[2]: <colorama.ansitowin32.StreamWrapper at 0x3a2aac8>
    
    In [3]: reload(sys)
    <module 'sys' (built-in)>
    
    In [4]: sys.stdout
    Out[4]: <open file '<stdout>', mode 'w' at 0x00000000022E20C0>
    
    In [11]: import IPython.terminal
    
    In [14]: IPython.terminal.interactiveshell.sys.stdout
    Out[14]: <colorama.ansitowin32.StreamWrapper at 0x3a9aac8>
  • अब, sys.setdefaultencoding()उचित

    यह सब प्रभावित करता है निहितार्थ रूपांतरण हैstr<->unicode । अब, utf-8ग्रह पर sanest एन्कोडिंग है (ASCII और सभी के साथ पीछे-संगत), अब रूपांतरण "बस काम करता है", क्या संभवतः गलत हो सकता है?

    खैर, कुछ भी। और यही खतरा है।

    • कुछ कोड हो सकते हैं जो UnicodeErrorगैर-एएससीआईआई इनपुट के लिए फेंके जाने पर निर्भर करते हैं , या एक त्रुटि हैंडलर के साथ ट्रांसकोडिंग करते हैं, जो अब एक अप्रत्याशित परिणाम पैदा करता है। और चूंकि सभी कोड को डिफ़ॉल्ट सेटिंग के साथ परीक्षण किया जाता है, आप यहां "असमर्थित" क्षेत्र पर कड़ाई से हैं , और कोई भी आपको इस बारे में गारंटी नहीं देता है कि उनका कोड कैसे व्यवहार करेगा।
    • ट्रांसकोडिंग अप्रत्याशित या अनुपयोगी परिणाम उत्पन्न कर सकता है यदि सिस्टम पर सब कुछ यूटीएफ -8 का उपयोग नहीं करता है क्योंकि पायथन 2 वास्तव में कई स्वतंत्र "डिफ़ॉल्ट स्ट्रिंग एन्कोडिंग" है । (याद रखें, एक कार्यक्रम ग्राहक के उपकरण पर काम करना चाहिए।)
      • फिर से, सबसे बुरी बात यह है कि आप कभी भी यह नहीं जान पाएंगे कि क्योंकि रूपांतरण निहित है - आप वास्तव में नहीं जानते कि यह कब और कहाँ होता है। (पायथन ज़ेन, कोन 2 आह!) आप कभी नहीं जान पाएंगे कि क्यों (और अगर) आपका कोड एक सिस्टम पर काम करता है और दूसरे पर टूटता है। (या बेहतर अभी तक, आईडीई में काम करता है और कंसोल में टूट जाता है।)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.