2010-12-07 6 views
35

पायथन 2 में डिफ़ॉल्ट आउटपुट एन्कोडिंग सेट करना एक प्रसिद्ध मुहावरे है:पायथन 3 में sys.stdout एन्कोडिंग कैसे सेट करें?

sys.stdout = codecs.getwriter("utf-8")(sys.stdout) 

यह sys.stdout ऑब्जेक्ट को कोडेक लेखक में लपेटता है जो यूटीएफ -8 में आउटपुट को एन्कोड करता है।

हालांकि, यह तकनीक पायथन 3 में काम नहीं करती है क्योंकि sys.stdout.write()str की अपेक्षा करता है, लेकिन एन्कोडिंग का परिणाम bytes है, और एक त्रुटि तब होती है जब codecs एन्कोडेड बाइट्स को मूल sys.stdout पर लिखने का प्रयास करता है।

पायथन 3 में ऐसा करने का सही तरीका क्या है?

+0

2to3 इन जैसे प्रश्नों के लिए एक उपयोगी उपकरण है। –

+0

@ डैन_वाटरवर्थ: मैंने पहले कोशिश करने के बारे में नहीं सोचा था, लेकिन मैंने अभी '2to3' की कोशिश की और उसने दिए गए कोड के लिए कोई भी बदलाव नहीं सुझाया। –

+3

यदि नया कोड काम नहीं करता है तो मैं सुझाव दूंगा कि आप इसे एक बग के रूप में जोड़ें। –

उत्तर

30

अजगर 3.1 sys.stdout के लिए io.TextIOBase.detach() कहा, दस्तावेज में एक नोट के साथ:

मानक धाराओं डिफ़ॉल्ट रूप से पाठ मोड में कर रहे हैं। इनके लिए बाइनरी डेटा लिखने या पढ़ने के लिए, अंतर्निहित बाइनरी बफर का उपयोग करें। उदाहरण के लिए, बाइट्स को stdout पर लिखने के लिए, sys.stdout.buffer.write(b'abc') का उपयोग करें। io.TextIOBase.detach() धाराओं का उपयोग डिफ़ॉल्ट रूप से बाइनरी किया जा सकता है। इस समारोह stdin और stdout सेट बाइनरी:

def make_streams_binary(): 
    sys.stdin = sys.stdin.detach() 
    sys.stdout = sys.stdout.detach() 
इसलिए

, अजगर 3.1 और बाद में हो, के लिए इसी मुहावरा:

sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) 
+5

मैं चाहता हूं 'पायथनियोएनकोडिंग' का प्रयोग करें; अन्यथा 'io.TextIOWrapper' न्यूलाइन ठीक से संभालने के लिए 'कोडेक्स' से बेहतर विकल्प हो सकता है। – jfs

+0

यह 'sys.stdout' के व्यवहार को पूरी तरह बदल देता है। 'Codecs.getwriter' द्वारा लौटाया गया 'स्ट्रीमवाइटर' अब लाइन-बफर्ड नहीं है, उदाहरण के लिए – Sebastian

7

sys.stdout पायथन 3. इसलिए आप में पाठ मोड में है सीधे यूनिकोड लिखें, और पायथन 2 के लिए मुहावरे की अब आवश्यकता नहीं है।

इस कहां अजगर 2 में विफल हो जाएगा:

>>> import sys 
>>> sys.stdout.write(u"ûnicöde") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfb' in position 0: ordinal not in range(128) 

हालांकि, यह अजगर 3 में सिर्फ dandy काम करता है:

>>> import sys 
>>> sys.stdout.write("Ûnicöde") 
Ûnicöde7 

अब अगर आपके अजगर पता नहीं है कि आपके stdouts एन्कोडिंग वास्तव में है , यह एक अलग समस्या है, जो पाइथन के निर्माण में सबसे अधिक संभावना है।

+2

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

+1

फिर भी एक और सबूत है कि प्रक्रिया संचार के लिए stdout का उपयोग करना बड़ी गलती है। मुझे एहसास है कि इस मामले में सीजीआई का उपयोग करने के अलावा आपके पास कोई विकल्प नहीं हो सकता है, हालांकि यह आपकी गलती नहीं है। :-) –

+0

हालांकि यह सच है कि 'sys.stdout' पायथन 2 में एक * बाइनरी * फ़ाइल है और पाइथन 3 में एक * टेक्स्ट * फ़ाइल है, मुझे लगता है कि आपका पायथन 2 उदाहरण विफल रहता है क्योंकि यूनिकोड स्ट्रिंग 'u" Ñnicöde "' जिसे 'sys.stdout.write' विधि में निहित रूप से एन्कोड किया जाता है, में ASCII रेंज के बाहर वर्ण होते हैं। यदि आप अपने 'एलसी_सीटीपीई', 'LANG' या' PythonioenCODING' पर्यावरण चर को एक एन्कोडिंग में बदलते हैं जिसमें यूनिकोड स्ट्रिंग में सभी वर्ण हैं तो आपको कोई त्रुटि नहीं मिलनी चाहिए। (मैंने पायथन 2.7 पर कोशिश की है।) – Maggyero

16

अजगर 2 में डिफ़ॉल्ट आउटपुट एन्कोडिंग स्थापना एक प्रसिद्ध मुहावरा

Eek है! क्या यह पाइथन 2 में एक प्रसिद्ध मुहावरे है? यह मेरे लिए एक खतरनाक गलती की तरह दिखता है।

यह निश्चित रूप से किसी भी स्क्रिप्ट को गड़बड़ कर देगा जो बाइनरी को stdout लिखने की कोशिश करता है (उदाहरण के लिए यदि आप एक सीजीआई स्क्रिप्ट एक छवि लौट रहे हैं तो आपको आवश्यकता होगी)। बाइट्स और चार्स काफी अलग जानवर हैं; बंदर को स्वीकार करने के लिए निर्दिष्ट एक इंटरफ़ेस बंदर-पैच करना एक अच्छा विचार नहीं है जो केवल चार्ज लेता है।

सीजीआई और HTTP सामान्य रूप से बाइट्स के साथ काम करते हैं। आपको केवल sys.stdout पर बाइट भेजना चाहिए। पायथन 3 में इसका मतलब है कि सीधे बाइट भेजने के लिए sys.stdout.buffer.write का उपयोग करना। अपने charset पैरामीटर से मेल खाने के लिए एन्कोडिंग पृष्ठ सामग्री को आपके एप्लिकेशन में उच्च स्तर पर संभाला जाना चाहिए (ऐसे मामलों में जहां आप बाइनरी के बजाय टेक्स्ट सामग्री को वापस कर रहे हैं)। इसका मतलब है कि print अब सीजीआई के लिए अच्छा नहीं है।

(भ्रम, wsgiref के CGIHandler तक py3k में टूट चुका है बहुत हाल ही में, यह असंभव है कि जिस तरह से सीजीआई को WSGI तैनात करने के लिए बनाने के लिए जोड़ने के लिए। पीईपी 3333 और अजगर 3.2 के साथ इस अंत में व्यावहारिक है।)

+0

इस टिप्पणी को अद्यतन करने की आवश्यकता है, 3.3 और आगामी 3.4 पायथन रिलीज के बारे में। धन्यवाद – soshial

18

मैं इस कम मुसीबत तो sys.stdout गमागमन अजगर है के बाद है - जबकि, एक ही त्रुटि के समाधान के लिए खोज

पहले से ही दिए गए सुझावों के लिए एक वैकल्पिक समाधान PYTHONIOENCODING वातावरण स्थापित करने के लिए चर से पहले अजगर अपने प्रयोग के लिए, शुरू होता है इस सूत्र पाया आरंभ किया गया:

PYTHONIOENCODING=utf-8:surrogateescape python3 somescript.py 

पायथन कोड को जाने और संपादित करने के लाभ के साथ।

+0

मुख्य रूप से थंबस-अपिंग क्योंकि PYTHONIOENCODING = utf-8 ने खोज के कई घंटों के बाद मेरी समस्या हल की। – theeggman85

5

detach() का कारण बनता है एक चेतावनी मुद्रित करने के लिए जब यह stdout बंद करने के लिए बस से पहले ही बाहर निकल जाता है की कोशिश करता है दुभाषिया का उपयोग करना:

Exception ignored in: <_io.TextIOWrapper mode='w' encoding='UTF-8'> 
ValueError: underlying buffer has been detached 

इसके बजाय, यह मेरे लिए ठीक काम किया:

default_out = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') 

(और, पाठ्यक्रम, stdout के बजाय default_out पर लिखना।)

15

अन्य उत्तर codecs का उपयोग करने की सलाह देते हैं, लेकिनमेरे लिएकाम करता है:

import sys 
sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8', buffering=1) 
print("日本語") 
# Also works with other methods of writing to stdout: 
sys.stdout.write("日本語\n") 
sys.stdout.buffer.write("日本語\n".encode()) 

यह भी काम करता है जब मैं PYTHONIOENCODING="ascii" साथ इसे चलाने के।

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