Django模型数据库插入有时会因未知编码错误而失败

时间:2015-06-23 17:33:17

标签: python mysql django encoding

我有一个大型程序,它使用Django作为后端工作流管理器,调用运行C编译的.so共享库的各种Python脚本。

该程序的一个这样的部分涉及分析阶段,因此通常它使用执行参数填充MySQL数据库表,然后在运行阶段之后使用运行时间,文件大小等填充另一个表。

一般代码如下:

from profiler.models import ProfileParameters, ProfileData, ProfileResults

# Populate dB with execution parameters
 ProfileData(profile_id=profile_number, profile_type=1, profile_param_id=1, profile_param_value=data).save()

# The above line always works

# call C .so
run_program.argtypes(...) # details ommited for brevity

# get run_times, etc.
run_time = get_runtimes()
total_file_size = get_filesize()

# Try to populate dB again
ProfileResults(profile_id=profile_number, profile_filesize_MB=total_file_size, profile_process_time_minutes = run_time).save()

脚本有时上次调用ProfileResults()时出现问题。有时候它会起作用,而有时却不起作用。当它不起作用时,我看到错误:

    ProfileResults(profile_id=profile_number, profile_filesize_MB=total_file_size, profile_process_time_minutes = total_time_minutes).save()
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 545, in save
    force_update=force_update, update_fields=update_fields)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 573, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 654, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 687, in _do_insert
    using=using, raw=raw)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 232, in _insert
    return insert_query(self.model, objs, fields, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 1514, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 903, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py", line 69, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py", line 53, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/base.py", line 124, in execute
    return self.cursor.execute(query, args)
  File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 157, in execute
    query = query.encode(charset)
LookupError: unknown encoding: PEh

所以,关键是,我认为是:

LookupError:未知编码:PEh

实际错误,在这种情况下包括一个不会在这里打印出来的字符。但是"未知编码"之后打印出来的是什么?变化,有时候是空白。

我认为当.so正在运行并打印到stdout时,编码正在以某种方式发生变化。

我尝试过:

reload(sys)
sys.setdefaultencoding("utf-8")

在调用ProfileResults()之前,但似乎没有效果。

我认为,最奇怪的是,它有时会起作用,有时也不起作用。但似乎它大部分都不起作用。

对ProfileResults()的调用中输入的内容似乎并不重要。如果我在它之前放置一个pdb.set_trace(),并使用硬编码值而不是变量来调用它,同样的事情就会发生。

1 个答案:

答案 0 :(得分:0)

似乎该问题与MySQL全局游标有关,其中未定义的东西可能在重复的数据库连接打开和关闭时发生。不知道我是否完全理解它......

无论如何,Python脚本调用的共享库也执行了一些数据库事务,因此打开和关闭了一个连接。从.so返回时,Python脚本遇到了一些奇怪的行为。

查看/usr/lib/Python2.7/dist-packages/MySQLdb/cursors.py,第155行:

charset = db.character_set_name()

这会返回空白,有时是乱码或有时正确的值。将此硬编码为'utf-8'解决了问题,但自然不是一个好的解决方案。

所以,似乎有效的是从.so返回时重新启动Django连接:

from django import db
db.close_connection()
from profiler.models import ProfileParameters, ProfileData, ProfileResults

到目前为止,现在一切都按预期工作了。有点令人厌烦的是没有完全理解这个问题,以及为什么这个解决方案有效,但很高兴知道它的确如此。它是一个Django错误,MySQL错误,还是根本没有错误?

任何人都有关于此的更多信息?