2010-10-18 61 views
4

我使用Twisted異步訪問Python中的數據庫。我的代碼如下所示:在Python中轉義MySQL的unicode字符串(避免exceptions.UnicodeEncodeError)

from twisted.enterprise import adbapi 
from MySQLdb import _mysql as mysql 

... 

txn.execute(""" 
    INSERT INTO users_accounts_data_snapshots (accountid, programid, fieldid, value, timestamp, jobid) 
    VALUES ('%s', '%s', '%s', '%s', '%s', '%s') 
""" % (accountid, programid, record, mysql.escape_string(newrecordslist[record]), ended, jobid)) 

這個工作,直到我遇到了這個角色:®,這導致線程拋出一個異常:`exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\xae' in position 7: ordinal not in range(128)

但是,如果我不使用MySQLdb_mysql.escape_string( ),當輸入包含引號等時(當然),我得到數據庫錯誤。在訪問數據庫之前發生異常,所以數據庫的整理似乎根本就不重要。

什麼是最好的方式逃脫這個內容,而不會拋出unicode字符的例外情況?理想的解決方案是我可以傳遞unicode字符,不會干擾MySQL的查詢;然而,剝離unicode字符串,用問號替換它們,將它們或其他任何可以停止崩潰的內容都可以接受。

回答

11

不要格式化字符串。這是一個巨大的安全漏洞。你不可能自己做正確的引用。不要嘗試。

使用第二個參數'執行'。簡單地說,而不是txn.execute("... %s, %s ..." % ("xxx", "yyy")),做txn.execute("... %s, %s ...", ("xxx", "yyy"))。注意逗號而不是百分號。在其他數據庫或不同的數據庫綁定中,您可能會使用不同的字符而不是「%s」,如?:1, :2, :3:foo:, :bar:, :baz:,但這個想法是相同的。 (如果您對替代品感興趣,您可以查看paramstyle in the DB-API 2.0 documentation的文檔。)

I've written about this in the past。關於這個職位的討論可能會對你特別感興趣。

請同時強調一下,這是唯一正確的方法。。您可能已經看到MySQL文檔討論以各種方式引用字符串。您可能已經使用PHP編寫了應用程序,該應用程序缺少傳遞數據庫參數的適當工具。我保證所有這些信息來源都不正確,並導致嚴重和持續的安全問題:不要將參數插入到SQL字符串中。

+1

這不僅工作,但現在我不必手動擠壓日期時間對象的字符串。非常感謝你。 – 2010-10-18 15:58:20

相關問題