Python Django syncdb在使用unicode字符串时表现异常

Python Django syncdb在使用unicode字符串时表现异常,python,django,unicode,virtualenv,rhel,Python,Django,Unicode,Virtualenv,Rhel,我要为这篇文章的篇幅提前道歉。我只是想确定我没有遗漏任何信息 我有一个应用程序在django应用程序之外使用django的ORM,它通过直接调用call\u命令('syncdb')使用“syncdb”(注意:我在下面列出的每个场景中都使用virtualenv) 我在应用程序中的单元测试尝试使用SQLite作为后端设置一个“测试”django数据库(而生产环境使用MySQL) 每次运行一个单元测试时,它都会在整个测试过程中使用相同的test django设置调用call_命令('syncdb')

我要为这篇文章的篇幅提前道歉。我只是想确定我没有遗漏任何信息

我有一个应用程序在django应用程序之外使用django的ORM,它通过直接调用
call\u命令('syncdb')
使用“syncdb”(注意:我在下面列出的每个场景中都使用virtualenv)

我在应用程序中的单元测试尝试使用SQLite作为后端设置一个“测试”django数据库(而生产环境使用MySQL)

每次运行一个单元测试时,它都会在整个测试过程中使用相同的test django设置调用
call_命令('syncdb')

我能够在两个不同的环境中运行这些单元测试(一个使用Windows 7/Python 2.7.3,另一个使用Mac OS X ML/Python 2.7.2)。测试没有任何问题;但在这两个平台上都安装了相对干净的Python

但是,当我尝试在RHEL服务器上运行此操作时,当单元测试尝试运行syncdb时,我会出现以下错误:

DatabaseError:表“my\u app\u mytable”已存在

经过大量令人沮丧的谷歌搜索和调试后,我(认为)我已经消除了报告的bug并进行了测试

我做了很多黑客攻击,我想我已经把问题缩小到了(听起来很疯狂)(第59行):

我在django的syncdb源代码中设置了一个
pdb.set_trace()
,在两种环境中都可以查看。以下是我的发现:

(有效的环境)

那里看起来不错。从syncdb文件的外观来看,django使用
tables
变量根据数据库中已有的内容检查应用程序的模型

(不起作用的环境)

除非我疯了,否则我认为这会使django的源返回中的以下语句为false:

def model_installed(model):
        opts = model._meta
        converter = connection.introspection.table_name_converter
        return not ((converter(opts.db_table) in tables) or
            (opts.auto_created and converter(opts.auto_created._meta.db_table) in tables))
此方法通过定义后几行的
filter
调用,它看起来像是检查
converter(opts.db_table)
是否在
tables
列表中。我也在这两种环境中手动运行了它们:

(有效的环境)

正如您所见,我(某种程度上)手动运行了
model\u installed
函数,查看
转换器(opts.db\u table)
返回的内容,在这两种环境中,它看起来都是一个非常正常的字符串。然而:

(不起作用的环境)

因此,它看起来像是因为
tables
变量是坏环境中看起来疯狂的crud列表,该方法错误地声称每个模型的表名不在数据库中,这给了我在开始时声明的原始错误

为了确保我没有发疯,我还尝试手动插入正确的列表进行比较:

(不起作用的环境)

我是否需要在此环境中重新编译Python?我阅读了关于stackoverflow的文章,发现我的坏环境表现出奇怪的行为:

(myvirtualenv)[username@myserver]$ python
Python 2.7.3 (default, Apr 12 2012, 10:40:11)
[GCC 4.4.6 20110731 (Red Hat 4.4.6-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import StringIO, cStringIO, sys
>>> StringIO.StringIO(u"fubar").getvalue()
u'fubar'
>>> cStringIO.StringIO(u"fubar").getvalue()
'fubar'
>>> cStringIO.StringIO(u"\u0405\u0406").getvalue()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
>>> sys.maxunicode
65535
>>> sys.byteorder
'little'
因此,我在python解释器中手动连接到sqlite文件,并运行该查询:

(不起作用的环境)


即使没有在顶部定义编码,“工作”环境在解释我的
模型
文件和正确创建表方面似乎没有任何问题。是否存在导致此问题的SQLite默认设置?或者git是否在坏环境中将文件转换为UTF-16LE,并在工作环境中使用UTF-8/ASCII?

您的文本编辑器已决定将文件另存为UTF-16LE


嗯,我的
sqlite3
模块似乎出了问题。最后我重新安装了Red Hat的
sqlite-devel
包,重新编译了Python 2.7.3,然后在virtualenv中更新了可执行文件

现在似乎工作得很好。现在,当我运行django的
get\u table\u list()
query时,我得到以下结果:

>>> import sqlite3
>>> conn = sqlite3.connect('/path/to/sqlite/file')
>>> curs = conn.cursor()
>>> curs.execute("""
... SELECT name FROM sqlite_master
... WHERE type='table' AND NOT name='sqlite_sequence'
... ORDER BY name""")
<sqlite3.Cursor object at 0xb7774ca0>
>>> curs.fetchall()
[(u'my_app_mytable',), (u'my_app_myothertable',)]
导入sqlite3 >>>conn=sqlite3.connect('/path/to/sqlite/file') >>>游标=连接游标() >>>curs.execute(“”) …从sqlite_master中选择名称 …其中type='table'而不是name='sqlite\u sequence' …按名称排序(“”) >>>curs.fetchall() [(我的应用程序我的表格,),(我的应用程序我的表格,)]
我没有对sqlite文件本身进行任何更改,因此这似乎是sqlite 3模块和/或Python 2.7.3安装的问题。

我遇到了类似的问题,相同的syncdb命令在一个环境中成功执行,而在另一个环境中没有使用相同的数据库导入和模型成功执行。 将
call_命令(syncdb)
更改为
os.system('python'+| path |,'manage.py syncdb'))
为我解决了这个问题


希望它能帮助其他人。

你从哪里得到了这个坏掉的
unicode
(实际上是UTF-16LE,除了它在
unicode
中)以及cStringIO与它有什么关系?在这个例子中,它看起来像
cStringIO.StringIO(u“fubar”)。getvalue()
调用返回一个类似
'f\x00u\x00b\x00a\x00r\x00'
的字符串。我想我可能看错了问题,我在问题中显示的行为是预期的行为吗?我用这种编码得到了奇怪的行为。我将它添加到源文件的顶部,但是我得到了一个
语法错误:无效语法
,它似乎指向EOF新行。
def model_installed(model):
        opts = model._meta
        converter = connection.introspection.table_name_converter
        return not ((converter(opts.db_table) in tables) or
            (opts.auto_created and converter(opts.auto_created._meta.db_table) in tables))
(Pdb) opts = all_models[0][1][0]._meta
(Pdb) converter = connection.introspection.table_name_converter
(Pdb) converter(opts.db_table) in tables
True
(Pdb) opts = all_models[0][1][0]._meta
(Pdb) converter = connection.introspection.table_name_converter
(Pdb) converter(opts.db_table) in tables
False
(Pdb) converter(opts.db_table) in [u'my_app_mytable', u'my_app_myothertable']
True
(myvirtualenv)[username@myserver]$ python
Python 2.7.3 (default, Apr 12 2012, 10:40:11)
[GCC 4.4.6 20110731 (Red Hat 4.4.6-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import StringIO, cStringIO, sys
>>> StringIO.StringIO(u"fubar").getvalue()
u'fubar'
>>> cStringIO.StringIO(u"fubar").getvalue()
'fubar'
>>> cStringIO.StringIO(u"\u0405\u0406").getvalue()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
>>> sys.maxunicode
65535
>>> sys.byteorder
'little'
def get_table_list(self, cursor):
    "Returns a list of table names in the current database."
    # Skip the sqlite_sequence system table used for autoincrement key
    # generation.
    cursor.execute("""
        SELECT name FROM sqlite_master
        WHERE type='table' AND NOT name='sqlite_sequence'
        ORDER BY name""")
    return [row[0] for row in cursor.fetchall()]
>>> import sqlite3
>>> conn = sqlite3.connect('/path/to/sqlite/file')
>>> curs = conn.cursor()
>>> curs.execute("""
... SELECT name FROM sqlite_master
... WHERE type='table' AND NOT name='sqlite_sequence'
... ORDER BY name""")
<sqlite3.Cursor object at 0xb7557500>
>>> curs.fetchall()
[(u'c\x00c\x00_\x00s\x00t\x00a\x00t\x00s\x00_\x00c\x00c\x00',), (u'c\x00c\x00_\x00s\x00t\x00a\x00t\x00s\x00_\x00c\x00c\x00s',)]
>>> curs.fetchall()
[(u'my_app_mytable',), (u'my_app_myothertable',)]
# -*- coding: utf-16le -*-
>>> import sqlite3
>>> conn = sqlite3.connect('/path/to/sqlite/file')
>>> curs = conn.cursor()
>>> curs.execute("""
... SELECT name FROM sqlite_master
... WHERE type='table' AND NOT name='sqlite_sequence'
... ORDER BY name""")
<sqlite3.Cursor object at 0xb7774ca0>
>>> curs.fetchall()
[(u'my_app_mytable',), (u'my_app_myothertable',)]