the5fire的技术博客

关注python、vim、linux、web开发和互联网--life is short, we need python.


调试PyPy运行Django出现的错误:Segmentation fault

作者:the5fire | 标签:       | 发布:2013-05-28 6:57 a.m. | 阅读量: 5423, 5316

前两天在家研究了下pypy,顺便也搭建了一个基于pypy的virtualenv环境: 创建基于pypy的virtualenv虚拟环境 ,在上篇文章最后说到在用django处理mysql数据库的时候会出现这个错误,然后崩溃:Segmentation fault (core dumped)。经过这两天使用pdb进行一步步debug,终于发现问题所在了。

从一个 python manage.py sql blog 开始,阅读了大部分的 django.db.backends.mysql 的代码,稍带着也看了MySQLdb库的一些代码,终于最后找到了问题所在。

在这个过程中,不断的对比Django中的cursor和正常情况下直接用MySQL代码创建的cursor,发现没有太多的区别,Django中的cursor其实是对MySQLdb创建出来的cursor的包装—— CursorWrapperCursorDebugWrapper (位于: django.db.backends.util ) ,其中后面这个CursorDebugWrapper和django_debug_toolbar有很重要的关系,这里面计算了每个连接的执行SQL语句以及每个语句的执行时间。而其他的cursor的操作没有什么特别的地方。

有逻辑的推敲代码还是很重要的,通过短路法不断的尝试,最后终于定位到了是Django在创建一个connection时发生的错误。查错的方法很简单,在pdb下,在Django创建完成一个connection之后,手动创建cursor,然后执行查询,发现直接抛错了。这说明这个connection创建的有问题。(文件位于: django.db.backends.mysql.base 中)

看一下这个connection的创建过程:

# ....省略代码
kwargs = {
    'conv': django_conversions,
    #'charset': 'utf8',
    #'use_unicode': True,
}
settings_dict = self.settings_dict
if settings_dict['USER']:
kwargs['user'] = settings_dict['USER']
if settings_dict['NAME']:
kwargs['db'] = settings_dict['NAME']
if settings_dict['PASSWORD']:
kwargs['passwd'] = force_str(settings_dict['PASSWORD'])
if settings_dict['HOST'].startswith('/'):
kwargs['unix_socket'] = settings_dict['HOST']
elif settings_dict['HOST']:
kwargs['host'] = settings_dict['HOST']
if settings_dict['PORT']:
kwargs['port'] = int(settings_dict['PORT'])
# We need the number of potentially affected rows after an
# "UPDATE", not the number of changed rows.
kwargs['client_flag'] = CLIENT.FOUND_ROWS
kwargs.update(settings_dict['OPTIONS'])
t_kwargs = {}
import pdb;pdb.set_trace()
#self.connection = Database.connect(db='django5',host='127.0.0.1',user='root',passwd='root')
self.connection = Database.connect(**kwargs)

# ... 省略代码

尝试后发现去掉创建链接时 charset和use_unicode的参数创建就能成功。

到此为止问题已经找出来了。至于这俩参数的具体用处,下回再说。

最后补充一句,Django没必要同时设置charset和use_unicode,因为MySQLdb库中有对应的判定:

charset = kwargs2.pop('charset', '')

if charset:
    use_unicode = True
else:
    use_unicode = False

当然,除非你设置charset后需要设置use_unicode为false:

use_unicode = kwargs2.pop('use_unicode', use_unicode)

----EOF-----

扫码关注,或者搜索微信公众号:码农悟凡


其他分类: