2009-07-20 13 views
5

में यूनिकोड कारखाना मुझे लगता है कि मैं एक SQL सर्वर डेटाबेस से पुन: प्राप्त करने हूँ एक अजगर 2.6 स्क्रिप्ट कि विशेष वर्ण, लैटिन -1 में एन्कोड पर gagging है,। मैं इन पात्रों को प्रिंट करना चाहता हूं, लेकिन मैं कुछ हद तक सीमित हूं क्योंकि मैं एक पुस्तकालय का उपयोग कर रहा हूं जो unicode फैक्ट्री को कॉल करता है, और मुझे नहीं पता कि पाइथन ascii के अलावा कोडेक का उपयोग कैसे करें।लैटिन -1 और अजगर

स्क्रिप्ट किसी SQL संपादक में सीधे एसक्यूएल निष्पादित करने के लिए बिना एक डेटाबेस से देखने डेटा लौटाने के लिए एक सरल उपकरण है। मैं परिणामों को प्रदर्शित करने के लिए PrettyTable 0.5 लाइब्रेरी का उपयोग करता हूं।

स्क्रिप्ट का मूल कोड का यह छोटा सा है। कर्सर से प्राप्त टुपल्स में पूर्णांक और स्ट्रिंग डेटा होता है, और कोई यूनिकोड डेटा नहीं होता है। (मैं pyodbc के बजाय adodbapi का उपयोग करेंगे, जो मुझे यूनिकोड मिलेगा, लेकिन adodbapi मुझे अन्य समस्याओं देता है।)

x = pyodbc.connect(cxnstring) 
r = x.cursor() 
r.execute(sql) 

t = PrettyTable(columns) 
for rec in r: 
    t.add_row(rec) 
r.close() 
x.close() 

t.set_field_align("ID", 'r') 
t.set_field_align("Name", 'l') 
print t 

लेकिन Name स्तंभ अक्षर है कि ASCII सीमा के बाहर गिर हो सकते हैं। मैं कभी कभी, इस तरह एक त्रुटि संदेश मिल जाएगा, prettytable.pyc के 222 लाइन में जब यह t.add_row कॉल करने के लिए हो जाता है:

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

यह prettytable.py में 222 लाइन है। यह unicode का उपयोग करता है, जो कि मेरी समस्याओं का स्रोत है, न केवल इस स्क्रिप्ट में, बल्कि अन्य पायथन स्क्रिप्ट्स में जो मैंने लिखा है।

for i in range(0,len(row)): 
    if len(unicode(row[i])) > self.widths[i]: # This is line 222 
     self.widths[i] = len(unicode(row[i])) 

कृपया मुझे बताएं कि मैं यहां क्या कर रहा हूं। मैं unicode कैसे हैकिंग prettytable.py या किसी भी अन्य पुस्तकालयों का उपयोग किए बिना काम कर सकता हूं? क्या ऐसा करने का कोई तरीका है?

संपादित करें: त्रुटि print कथन पर नहीं है, लेकिन t.add_row पर कॉल करें।

संपादित करें: Bastien Léonard की मदद से, मैं निम्नलिखित समाधान के साथ आया था। यह एक पैनसिया नहीं है, लेकिन यह काम करता है।

x = pyodbc.connect(cxnstring) 
r = x.cursor() 
r.execute(sql) 

t = PrettyTable(columns) 
for rec in r: 
    urec = [s.decode('latin-1') if isinstance(s, str) else s for s in rec] 
    t.add_row(urec) 
r.close() 
x.close() 

t.set_field_align("ID", 'r') 
t.set_field_align("Name", 'l') 
print t.get_string().encode('latin-1') 

मैं रास्ते में डीकोड करने और रास्ते पर एन्कोड करने के लिए समाप्त हो गया। यह सब मुझे आशा करता है कि हर कोई अपने पुस्तकालयों को बाद में पाइथन 3.x में बंद कर देता है!

उत्तर

5

मॉड्यूल की शुरुआत में इस जोड़ें:

# coding: latin1 

या स्ट्रिंग अपने आप को यूनिकोड को डिकोड।

[संपादित करें]

इसके बाद से मैं यूनिकोड के साथ खेला जाता है, लेकिन उम्मीद है कि इस उदाहरण लेटिन 1 से यूनिकोड में बदलने के लिए कैसे दिखा देंगे एक समय हो गया है:

>>> s = u'ééé'.encode('latin1') # a string you may get from the database 
>>> s.decode('latin1') 
u'\xe9\xe9\xe9' 

[संपादित करें]

प्रलेखन :
http://docs.python.org/howto/unicode.html
http://docs.python.org/library/codecs.html

+0

मैंने अपनी स्क्रिप्ट के शीर्ष पर कोडिंग डालने का प्रयास किया है, लेकिन यह अभी भी काम नहीं करता है। मैं स्पष्ट डिकोडिंग का प्रयास करूंगा, लेकिन मुझे आशा है कि एक और सामान्य समाधान होगा। – eksortso

+1

शायद आप कोडिंग सेट नहीं करना चाहते हैं: latin1। इससे स्क्रिप्ट के स्रोत के एन्कोडिंग में परिवर्तन होता है, न कि इसका डेटा। –

+0

@Glenn: मैंने सुझाव दिया कि क्योंकि मैंने सोचा था कि 'प्रिंट टी' लैटिन 1 कच्चे तारों को प्रिंट कर सकता है। –

2

शायद लैटिन 1-एन्कोडेड तारों को यूनिकोड में डीकोड करने का प्रयास करें?

t.add_row((value.decode('latin1') for value in rec)) 
+1

t.add_row ([s.decode ('latin-1') अगर isinstance (s, str) एसएस में रिक के लिए है तो]] # मुझे लगता है कि आप इसका मतलब था (या ऐसा कुछ)। – eksortso

+0

शायद, उस सुंदर चीज़ चीज़ की आवश्यकता के आधार पर। – liori

0

PrettyTable के लिए स्रोत इसकी एक झलक लेने के बाद, ऐसा लगता है कि वह आंतरिक रूप से यूनिकोड वस्तुओं पर काम करता है (देखें _stringify_row, add_row और add_column, उदाहरण के लिए)। चूंकि यह नहीं जानता कि आपके इनपुट स्ट्रिंग का एन्कोडिंग क्या उपयोग कर रहा है, यह डिफ़ॉल्ट एन्कोडिंग, usually ascii का उपयोग करता है।

अब ascii लैटिन -1 के सबसेट है, जिसका अर्थ है कि यदि आप एसीआई से लैटिन -1 में परिवर्तित हो रहे हैं, तो आपको कोई समस्या नहीं होनी चाहिए। हालांकि उलट, सच नहीं है; सभी लैटिन -1 अक्षर एसीआईआई अक्षरों के लिए मानचित्र नहीं हैं। इस प्रदर्शन करने के लिए:

>>> s = u'\xed\x31\x32\x33' 
>>> print s 
# FAILS: Python calls "s.decode('ascii')", but ascii codec can't decode '\xed' 
>>> print s.decode('ascii') 
# FAILS: Same as above 
>>> print s.decode('latin-1') 
í123 

स्पष्ट रूप से यूनिकोड को तार (जैसे आप अंततः) IMO चीजों को ठीक करता है, और अधिक समझ में आता है, परिवर्तित - आप और अधिक जानना चाहते हैं कि आपके डेटा का उपयोग कर रहा है, की तुलना में शब्दसमुच्चय की संभावना हो PrettyTable के लेखक :)। बीटीडब्लू, s.decode('latin-1')unicode(s, 'latin-1') के साथ s.decode('latin-1') को बदलकर आप अपनी सूची समझ में स्ट्रिंग के लिए चेक को छोड़ सकते हैं क्योंकि सभी ऑब्जेक्ट्स को तारों पर ले जाया जा सकता है।

एक आखिरी बात: अपने डेटाबेस और तालिकाओं के चरित्र सेट को देखना न भूलें - आप कोड में 'लैटिन -1' नहीं मानना ​​चाहते हैं, जब डेटा वास्तव में कुछ और के रूप में संग्रहीत किया जा रहा है (डेटाबेस में 'utf-8'?)। MySQL में, आप SHOW CREATE TABLE <table_name> कमांड का उपयोग यह पता लगाने के लिए कर सकते हैं कि तालिका किस तालिका का उपयोग कर रही है, और SHOW CREATE DATABASE <db_name> डेटाबेस के लिए ऐसा करने के लिए।

+0

यदि यह आंतरिक रूप से यूनिकोड ऑब्जेक्ट्स का उपयोग कर रहा है, तो यूनिकोड ऑब्जेक्ट्स को वापस पाने और उन्हें आगे और पीछे परिवर्तित करने से बचने का एक तरीका होना चाहिए। जब तक आप हमेशा यूनिकोड ऑब्जेक्ट्स का उपयोग करते हैं, तब तक आप इस गड़बड़ी से बचते हैं (इस तरह पाइथन 3 हमेशा काम करता है)। –

+0

मेरा मानना ​​है कि यह करता है: "get_string"। – elo80ka

+0

@ elo80ka, डेटा वास्तव में लैटिन -1 के रूप में संग्रहीत किया जाता है। मैंने स्क्रिप्ट लिखने से पहले सत्यापित किया। इसके अलावा (कम से कम पायथन 2.6 में), 'यूनिकोड (int_value,' लैटिन -1 ') का उपयोग करके इनट्स को मजबूर नहीं किया जा सकता है, भले ही' यूनिकोड (int_value) 'काम करता है। @ ग्लेन मेनार्ड, परिणामों को प्रिंट करने में एक डीकोड शामिल है, स्पष्ट रूप से परिभाषित किया गया है या नहीं। मुझे 't.get_string()। एनकोड ('लैटिन -1') ' हाँ, मैं py3k के व्यापक गोद लेने की उम्मीद कर रहा हूं, ताकि सभी तार यूनिकोड हों। यह बहुत परेशानी बचाएगा। – eksortso

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