Python/Django/MySQL "Incorrect string value"错误

标签 python mysql django unicode

我正在运行 Django 1.4.2/Python 2.7.3/MySQL 5.5.28 站点。该站点的一个功能是管理员可以向服务器发送电子邮件,服务器通过 procmail 调用 Python 脚本来解析电子邮件并将其扔到数据库中。我维护网站的两个版本——一个开发网站和一个生产网站。这两个站点使用不同但相同的 vitualenvs(我什至删除了它们并重新安装了所有软件包以确保)。

我遇到了一个奇怪的问题。 完全相同的脚本在开发服务器上成功,但在生产服务器上失败。它失败并出现此错误:

...django/db/backends/mysql/base.py:114: Warning: Incorrect string value: '\x92t kno...' for column 'message' at row 1

我很清楚 Django 的 unicode 问题,我知道这里有很多关于这个错误的问题,但我确保从一开始就将数据库设置为 UTF-8:

mysql> show variables like "character_set_database";
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| character_set_database | utf8  |
+------------------------+-------+
1 row in set (0.00 sec)

mysql> show variables like "collation_database";
+--------------------+-----------------+
| Variable_name      | Value           |
+--------------------+-----------------+
| collation_database | utf8_general_ci |
+--------------------+-----------------+
1 row in set (0.00 sec)

此外,我知道每一列都可以有自己的字符集,但 message 列确实是 UTF-8:

mysql> show full columns in listserv_post;
+------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| Field      | Type         | Collation       | Null | Key | Default | Extra          | Privileges                      | Comment |
+------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| id         | int(11)      | NULL            | NO   | PRI | NULL    | auto_increment | select,insert,update,references |         |
| thread_id  | int(11)      | NULL            | NO   | MUL | NULL    |                | select,insert,update,references |         |
| timestamp  | datetime     | NULL            | NO   |     | NULL    |                | select,insert,update,references |         |
| from_name  | varchar(100) | utf8_general_ci | NO   |     | NULL    |                | select,insert,update,references |         |
| from_email | varchar(75)  | utf8_general_ci | NO   |     | NULL    |                | select,insert,update,references |         |
| message    | longtext     | utf8_general_ci | NO   |     | NULL    |                | select,insert,update,references |         |
+------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
6 rows in set (0.00 sec)

有人知道我为什么会收到此错误吗?为什么它发生在生产配置下而不是开发配置下?

谢谢!

[编辑1]
需要明确的是,数据也是相同的。我向服务器发送一封电子邮件,procmail 将其发送出去。这是 .procmailrc 的样子:

VERBOSE=off
:0
{
    :0c
    | <path>/dev/ein/scripts/process_new_mail.py dev > outputdev

    :0
    | <path>/prd/ein/scripts/process_new_mail.py prd > outputprd
}

有 2 个 process_new_mail.py 副本,但这只是因为它是版本控制的,所以我可以维护两个独立的环境。如果我比较两个输出文件(其中包含收到的消息),它们是相同的。

[编辑 2] 我实际上刚刚发现 dev 和 prd 配置都失败了。不同之处在于开发配置静默失败(可能与 DEBUG 设置有关?)。问题是其中一条消息中有一些 unicode 字符,而 Django 出于某种原因对它们感到窒息。我正在进步....

我已经尝试编辑代码以将消息显式编码为 ASCII 和 UTF-8,但它仍然无法正常工作。不过,我越来越近了。

最佳答案

我修好了!问题是我没有根据字符集正确解析电子邮件。我固定的邮件解析代码来自this postthis post :

#get the charset of an email
#courtesy http://ginstrom.com/scribbles/2007/11/19/parsing-multilingual-email-with-python/
def get_charset(message, default='ascii'):
    if message.get_content_charset():
        return message.get_content_charset()

    if message.get_charset():
        return message.get_charset()

    return default

#courtesy https://stackoverflow.com/questions/7166922/extracting-the-body-of-an-email-from-mbox-file-decoding-it-to-plain-text-regard
def get_body(message):
    body = None

    #Walk through the parts of the email to find the text body.
    if message.is_multipart():
        for part in message.walk():
            #If part is multipart, walk through the subparts.
            if part.is_multipart():
                for subpart in part.walk():
                    if subpart.get_content_type() == 'text/plain':
                        #Get the subpart payload (i.e., the message body).
                        charset = get_charset(subpart, get_charset(message))
                        body = unicode(subpart.get_payload(decode=True), charset)
            #Part isn't multipart so get the email body.
            elif part.get_content_type() == 'text/plain':
                charset = get_charset(subpart, get_charset(message))
                body = unicode(part.get_payload(decode=True), charset)
    #If this isn't a multi-part message then get the payload (i.e., the message body).
    elif message.get_content_type() == 'text/plain':
        charset = get_charset(subpart, get_charset(message))
        body = unicode(message.get_payload(decode=True), charset)

    return body

非常感谢您的帮助!

关于Python/Django/MySQL "Incorrect string value"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13464405/

相关文章:

Python 2.7 方法解析顺序覆盖

python - 使用另一个包导入的包是不是 unpythonic,还是我应该直接导入它?

mysql - 使用索引,使用临时,使用文件排序 - 如何解决这个问题?

python - 如何在 Django 中自动更改模型字段

python - 匹配文本中存储的关键字/短语

python - 我应该使用哪个 OpenGL 基元来绘制三角剖分?

python - 在我的包的子包中运行 python 脚本

php - 在 phpmyadmin 中查询成功,在 php 中查询失败

mysql - 以月和年计算年龄或将秒数格式化为年和月?

python - django ModelAdmin 中的高级查询集。属性错误: 'dict' object has no attribute '_meta'