2017-08-30 55 views
0

我目前正在做一個項目,其中包括從SMTP服務器讀取日誌文件,並提取有關每個通過的電子郵件的有意義的信息。我有一張表,其中有一些列稍後將與搜索相關;垃圾郵件分數,域名,域名,時間戳,主題等。 一切正常,直到我遇到一些非ASCII字符,通常在主題字段(如預期的)。保存unicode到sqlite的問題

我試圖將str解碼爲iso-8859-1(這是該文件的編碼)並保存,並且我也嘗試將其編碼回UTF-8,並且說實話,我這裏有點迷路了。我聽說在Python 2.7中使用unicode是一場噩夢,但直到現在,我從未體驗過它。

無論如何,讓我解釋一下。這是我如何提取主題:

if 'subject' in realInfo: 
emailDict[keywrd].setSubject(realInfo[realInfo.index('subject') + 
len('subject') + 1:].decode('ISO-8859-1')) 

emailDict是一個字典,其中包含所有正在處理的電子郵件。

這就是我怎樣,我將一切都變成了數據庫:

info = (e.getID(), str(e.getSpamScore()), str(e.getMCPScore()), " ".join(e.getFrom()), " ".join(e.getTo()), e.getStatus(), e.getTimestamp(), e.getSubject(), dumps(e)) 
    print repr(e.getSubject()) # DEBUG 
    print type(e.getSubject()) # DEBUG 
    self.conn.cursor().execute(u"INSERT INTO emails (emailID, SpamScore, MCPScore, FromDomain, ToDomain, status, timestamp, subject, object)" 
         " VALUES (?,?,?,?,?,?,?,?,?)", info) 
    self.conn.commit() 

我加2個print語句來幫助我瞭解問題的所在。

'e'是一個電子郵件對象,用作每個電子郵件的藍圖。它包含以前由口譯員獲得的信息。之後,我將保存最重要的信息,如前所述,將用於搜索(「對象」列是一個電子郵件對象,在此使用pickle)。但只要特殊字符的出現,將引發一個異常:

u'VPXL \xffM-^W no more compromises. Better size, better life. \n' 
<type 'unicode'> 
Exception in thread Thread-25: 
Traceback (most recent call last): 
File "/usr/local/lib/python2.7/threading.py", line 801, in __bootstrap_inner 
self.run() 
File "/usr/local/lib/python2.7/threading.py", line 754, in run 
self.__target(*self.__args, **self.__kwargs) 
File "/ProjMail/projMail_lib.py", line 174, in refresher 
self.interpreter.start() 
File "/ProjMail/projMail_lib.py", line 213, in start 
c.save(self.emailTracker) 
File "/ProjMail/projMail_lib.py", line 56, in save 
self.saveEmails() 
File "/ProjMail/projMail_lib.py", line 62, in saveEmails 
else: self.add(key) # If it's new 
File "/ProjMail/projMail_lib.py", line 82, in add 
" VALUES (?,?,?,?,?,?,?,?,?)", info) 

ProgrammingError: You must not use 8-bit bytestrings unless you use a 
text_factory that can interpret 8-bit bytestrings (like text_factory = str). 
It is highly recommended that you instead just switch your application to 
Unicode strings.   

從我所看到的,它是Unicode,所以我不明白爲什麼SQLite是抱怨。 任何想法我可能在這裏做錯了嗎?提前致謝!

回答

0

問題是沒有將主題本身插入數據庫,它插入了醃漬Email實例。

>>> subject = u'VPXL \xffM-^W no more compromises. Better size, better life. \n' 
>>> conn = sqlite3.connect(':memory:') 
>>> c = conn.cursor()        
>>> c.execute("""CREATE TABLE foo (bar text, baz text)""")         
<sqlite3.Cursor object at 0x7fab5cf280a0> 
>>> c.execute("""INSERT INTO foo VALUES (?, ?)""", (subject, 'random text')) 
<sqlite3.Cursor object at 0x7fab5cf280a0> 

>>> class Email(object):pass 
... 
>>> e = Email() 
>>> e.subject = subject 
>>> c.execute("""INSERT INTO foo VALUES (?, ?)""", (subject, pickle.dumps(e))) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
sqlite3.ProgrammingError: You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings. 

採蓮Email實例創建混合編碼字節字符串內部,引發異常(即使只選擇將subject做到這一點)。

爲了防止異常時,您可以在連接的text_factory屬性更改爲str

>>> conn.text_factory = str 
>>> c.execute(stmt2, (subject, pickle.dumps(e))) 
<sqlite3.Cursor object at 0x7fab5b3343b0> 

如果您希望使用默認unicodetext_factory留着,你可以在醃製類存放在blob列,裹着一個buffer實例。

>>> conn.text_factory = unicode 
>>> c.execute("""CREATE TABLE foo2 (bar text, baz blob)""") 
>>> c.execute("""INSERT INTO foo VALUES (?, ?)""", (subject, buffer(pickle.dumps(e))))      
<sqlite3.Cursor object at 0x7fab5b3343b0> 

醃製實例恢復上檢索:

>>> c.execute("""SELECT bar, baz FROM foo2""") 
<sqlite3.Cursor object at 0x7fab5b3343b0> 
>>> res = c.fetchone() 
>>> res 
(u'VPXL \xffM-^W no more compromises. Better size, better life. \n', <read-write buffer ptr 0x7fab5e9706c8, size 167 at 0x7fab5e970688>) 
>>> pickle.loads(res[1]) 
<__main__.Email object at 0x7fab5b333ad0> 
+0

我做了你的建議,和它的工作!非常感謝! –