在Python中转义MySQL的unicode字符串(避免异常.UnicodeEncodeError)

时间:2010-10-18 06:04:27

标签: python mysql twisted

我使用Twisted在Python中异步访问我们的数据库。我的代码如下所示:

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字符串,用问号替换它们,修改它们或其他任何可以阻止崩溃的东西都是可以接受的。

2 个答案:

答案 0 :(得分: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 :(得分:2)

您可以尝试:

newrecordslist [记录] .decode( “UTF-8”)

Glyph是关于http://www.python.org/dev/peps/pep-0249/的。