2012-10-10 4 views
6

के साथ काम नहीं करता है जब मैं पायथन में sysadmin स्क्रिप्ट लिख रहा हूं, sys.stdout पर बफर जो प्रिंट करने के लिए हर कॉल को प्रभावित करता है), क्योंकि मैं डॉन करता हूं एक बफर को फ्लश करने की प्रतीक्षा नहीं करना है और फिर स्क्रीन पर एक बार लाइनों का एक बड़ा हिस्सा प्राप्त करना चाहते हैं, इसके बजाय मैं स्क्रिप्ट द्वारा नए आउटपुट उत्पन्न होने के तुरंत बाद आउटपुट की अलग-अलग लाइनों को प्राप्त करना चाहता हूं। मैं न्यूलाइन के लिए भी इंतजार नहीं करना चाहता हूं इसलिए आउटपुट देखें।पायथन मानक idiom sys.stdout buffer को शून्य पर सेट करने के लिए यूनिकोड

एक अक्सर मुहावरा इस्तेमाल किया अजगर में यह करने के लिए

import os 
import sys 
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0) 

यह एक लंबे समय के लिए मेरे लिए ठीक काम किया है। अब मैंने देखा, कि यह यूनिकोड के साथ काम नहीं करता है।

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

from __future__ import print_function, unicode_literals 

import os 
import sys 

print('Original encoding: {}'.format(sys.stdout.encoding)) 
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0) 
print('New encoding: {}'.format(sys.stdout.encoding)) 

text = b'Eisb\xe4r' 
print(type(text)) 
print(text) 

text = text.decode('latin-1') 
print(type(text)) 
print(text) 

यह निम्न उत्पादन की ओर जाता है:: कृपया निम्न स्क्रिप्ट देख

Original encoding: UTF-8 
New encoding: None 
<type 'str'> 
Eisb▒r 
<type 'unicode'> 
Traceback (most recent call last): 
    File "./export_debug.py", line 18, in <module> 
    print(text) 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 4: ordinal not in range(128) 

यह मुझे इसके लिए कारण नीचे ट्रैक करने के लिए घंटे लगे (अपने मूल स्क्रिप्ट इस न्यूनतम डिबगिंग स्क्रिप्ट से बहुत लंबे समय तक था)। यह लाइन

sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0) 

जो मैंने वर्षों से उपयोग की थी, इसलिए इससे कोई समस्या नहीं थी। बस इस लाइन पर टिप्पणी करें और सही आउटपुट इस तरह दिखना चाहिए:

Original encoding: UTF-8 
New encoding: UTF-8 
<type 'str'> 
Eisb▒r 
<type 'unicode'> 
Eisbär 

तो स्क्रिप्ट का क्या मतलब है? मेरी अजगर 2.7 कोड तैयार करने के लिए अधिक से अधिक निकट अजगर 3.x के लिए, मैं हमेशा उपयोग कर रहा हूँ

from __future__ import print_function, unicode_literals 

जो अजगर नया प्रिंट का उपयोग करता है() - समारोह लेकिन अधिक महत्वपूर्ण: यह अजगर की दुकान सभी स्ट्रिंग्स के रूप में आता है डिफ़ॉल्ट रूप से आंतरिक रूप से यूनिकोड। मैं लैटिन -1/ISO-8859-1 इनकोडिंग डेटा का एक बहुत कुछ है, उदाहरण के लिए

text = b'Eisb\xe4r' 

इसके साथ काम करने का इरादा भी तरह से, मैं यूनिकोड को यह पहली डिकोड करने के लिए की जरूरत है, कि क्या

text = text.decode('latin-1') 

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

अब यह सब सामान्य रूप से ठीक काम करता है, अभी तक शून्य बाइट आउटपुट बफर के साथ नहीं। कोई विचार? मैंने देखा कि sys.stdout.encoding शून्य-बफरिंग लाइन के बाद अनसेट है, लेकिन मुझे नहीं पता कि इसे फिर से कैसे सेट करें। यह केवल पढ़ने योग्य विशेषता है और ओएस पर्यावरण चर LC_ALL या LC_CTYPE को केवल पाइथन दुभाषिया की शुरुआत में ही मूल्यांकन किया जाता है।

बीटीडब्ल्यू .: 'इस्बर्' 'ध्रुवीय भालू' के लिए जर्मन शब्द है।

+0

@martineau ठीक है, sys.stdout = codecs.getwriter ('utf8') (sys.stdout) प्रस्ताव या तो काम नहीं करता है। मैंने वास्तव में बहुत कोशिश की और खोज की। तो मुझे लगता है कि बिना परीक्षण किए विचारों को लगता है कि ज्यादा मदद नहीं करते हैं। –

+0

मैंने आपके लिए प्रश्न माइग्रेट कर दिया है। अगली बार, मॉडरेटर ध्यान के लिए बस 'ध्वज' और हमें बताएं कि आपको क्या चाहिए! :) – slhck

+0

@ मार्टनलेहमान: तथ्य यह है कि यह अनचाहे था इसलिए मैंने इसे एक टिप्पणी के रूप में एक टिप्पणी के रूप में पोस्ट किया। – martineau

उत्तर

6

प्रिंट समारोह जब किसी फ़ाइल वस्तु के लिए लिख, यूनिकोड करने वाली बाइट्स रूपांतरण करने के लिए आउटपुट एन्कोडिंग को पुनः प्राप्त करने अजगर सी एपीआई के PyFile_WriteObject समारोह के कारण, और stdout धारा को बदल कर आप खो दिया एक विशेष ध्वज का उपयोग करता है एन्कोडिंग दुर्भाग्य से, आप स्पष्ट रूप से इसे फिर से निर्धारित नहीं कर सकते:

encoding = sys.stdout.encoding 
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0) 
sys.stdout.encoding = encoding # Raises a TypeError; readonly attribute 

तुम भी io.open function बजाय उपयोग नहीं कर सकते, क्योंकि यह अगर तुम encoding विकल्प की आवश्यकता होगी का उपयोग करने में सक्षम होना चाहते बफरिंग अक्षम होने की अनुमति नहीं है।

def print(*args, **kw): 
    flush = kw.pop('flush', True) # Python 2.7 doesn't support the flush keyword.. 
    __builtins__.print(*args, **kw) 
    if flush: 
     sys.stdout.flush() 
: अगर है कि हर जगह को जोड़ने के लिए, एक कस्टम प्रिंट समारोह उपयोग करने पर विचार भी कठिन है

print(something, flush=True) 

:

प्रिंट समारोह फ्लश तुरंत करने के लिए उचित तरीके से flush=True कीवर्ड का उपयोग करने के लिए है

चूंकि पायथन 2.7 के print() फ़ंक्शन वास्तव में समर्थन फ्लश कीवर्ड अभी तक (परेशानी) का समर्थन नहीं करता है, तो आप अनुकरण कर सकते हैं कि उस कस्टम संस्करण में एक स्पष्ट फ्लश जोड़कर।

+0

आप इसके साथ अपने कस्टम 'प्रिंट()' फ़ंक्शन की तीन पहली पंक्तियों को प्रतिस्थापित कर सकते हैं: 'flush = kw.pop ('flush', True)'। – Tadeck

+0

@Tadeck: महान सुझाव, जोड़ा गया। –

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