Django: DatabaseError: рядом с nyny����1: синтаксическая ошибка

Код:

>>> from django.core import serializers
>>> objects = serializers.deserialize('xml', fixturestr.encode('utf8'))
>>> o = next(objects)
>>> o
<DeserializedObject: countries.Country(pk=AF)>
>>> type(o)
<class 'django.core.serializers.base.DeserializedObject'>
>>> dir(o)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'm2m_data', 'object', 'save']
>>> o.save()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/marcintustin/oneclickrep/oneclickcosvirt/lib/python2.7/site-packages/django/core/serializers/base.py", line 165, in save
    models.Model.save_base(self.object, using=using, raw=True)
  File "/home/marcintustin/oneclickrep/oneclickcosvirt/lib/python2.7/site-packages/django/db/models/base.py", line 524, in save_base
    manager.using(using).filter(pk=pk_val).exists())):
  File "/home/marcintustin/oneclickrep/oneclickcosvirt/lib/python2.7/site-packages/django/db/models/query.py", line 562, in exists
    return self.query.has_results(using=self.db)
  File "/home/marcintustin/oneclickrep/oneclickcosvirt/lib/python2.7/site-packages/django/db/models/sql/query.py", line 441, in has_results
    return bool(compiler.execute_sql(SINGLE))
  File "/home/marcintustin/oneclickrep/oneclickcosvirt/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 818, in execute_sql
    cursor.execute(sql, params)
  File "/home/marcintustin/oneclickrep/oneclickcosvirt/lib/python2.7/site-packages/django/db/backends/util.py", line 40, in execute
    return self.cursor.execute(sql, params)
  File "/home/marcintustin/oneclickrep/oneclickcosvirt/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 337, in execute
    return Database.Cursor.execute(self, query, params)
DatabaseError: near "????????������������????����������������????������������������������????????��������������������������������������������????????����1": syntax error

Запрос и параметры:

(Pdb) query
u'SELECT (1) AS "a" FROM "country" WHERE "country"."iso" = ?  LIMIT 1'
(Pdb) params
(u'AF',)

Честно говоря, я в тупике - я даже не знаю, куда идти с этим. Запрос даже не должен быть таким длинным, как представленный ужас. Сообщение об ошибке также не декодируется как utf-8.

Основная задача состоит в том, чтобы прочитать фикстуру xml и отправить ее в базу данных. К сожалению, стандартная команда loaddata не может справиться с символами, отличными от ascii, в utf-8 xml (см. другие мои недавние вопросы, если вам интересно). По этой причине я пытаюсь сделать то, что делает loaddata, но вручную, чтобы передать десериализатору кодированные байты utf-8.

Запуск python 2.7.5 с django 1.4 в Linux.

Я буду признателен за способ полностью избежать этой проблемы или за любые подсказки о том, как решить или даже дополнительно диагностировать ее.

Обновление: это результат попытки выполнить запрос вручную:

>>> import sqlite3
>>> conn = sqlite3.connect('database.sqlite3.db')
>>> c = conn.cursor()
>>> c.execute(u'SELECT (1) AS "a" FROM "country" WHERE "country"."iso" = ?  LIMIT 1', (u'AF',))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
OperationalError: near "????????������������????����������������????������������������������????????��������������������������������������������????????����1": syntax error
>>> c.execute(u'SELECT (1) AS "a" FROM "country" WHERE "country"."iso" = AF  LIMIT 1')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
OperationalError: near "????????������������????����������������????������������������������????????������������������������������������????����????????��������": syntax error
>>> c.execute(u'SELECT * from "country" WHERE "country"."iso" = AF  LIMIT 1')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
OperationalError: near "????????����������������������������������������????��������������������������������������������????����????????����1����": syntax error
>>> c.execute(u'SELECT * from "country"')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
OperationalError: near "????????������������������������������������": syntax error
>>> c.execute('SELECT * from "country"')
<sqlite3.Cursor object at 0x4123f10>
>>> 

Мой терминал настроен на использование utf-8. Непонятно, почему передача объекта Unicode происходит так ужасно неправильно.

Обновление 2: это информация о версии для sqlite:

>>> sqlite3.version_info
(2, 6, 0)
>>> sqlite3.sqlite_version_info
(3, 7, 11)
>>> sqlite3.sqlite_version
'3.7.11'
>>> sqlite3.x
'11'
>>>

обновление 3: одна и та же ошибка возникает для каждой таблицы в базе данных при попытке использовать строки Unicode.

обновление 4: та же ошибка влияет на свежие базы данных. Вот результат запуска пример кода из документации python, а затем попытка выполнить юникод запрос:

>>> conn.close()
>>> conn = sqlite3.connect('example.db')
>>> c = conn.cursor()
>>> 
>>> # Create table
>>> c.execute('''CREATE TABLE stocks
...              (date text, trans text, symbol text, qty real, price real)''')
<sqlite3.Cursor object at 0x43e9180>
>>> 
>>> # Insert a row of data
>>> c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
<sqlite3.Cursor object at 0x43e9180>
>>> 
>>> # Save (commit) the changes
>>> conn.commit()
>>> c.execute(u'SELECT * FROM "stocks"')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
OperationalError: near "????????��������????????��������������������": syntax error
>>> 

Обновление 5: пакет, который предоставляет библиотеки sqlite, — sqlite-3.7.11-3.fc17.x86_64.


person Marcin    schedule 29.10.2013    source источник
comment
Это происходит постоянно или только несколько раз fixturestr?   -  person Benjamin Toueg    schedule 30.10.2013
comment
@btoueg У меня только одно приспособление.   -  person Marcin    schedule 30.10.2013
comment
Правильно ли работает тот же запрос из командной строки клиента sqlite3?   -  person Austin Phillips    schedule 30.10.2013
comment
@ОстинФиллипс Да. Фактически, он отлично работает с python, если запрос передается как байтовая строка (см. Обновление для этого). Однако, учитывая, что код сохранения django использует unicode, я не могу переписать его, чтобы сначала правильно кодировать все запросы.   -  person Marcin    schedule 30.10.2013
comment
Кстати, это основная причина исключения, показанного в вашем django loaddata, настаивает на чтении xml-фикстуры как ascii-вопроса. У Django на самом деле нет проблем с чтением вашего XML UTF-8, но у него проблемы с созданием сообщения об ошибке, которое он пытается использовать для переноса этого DatabaseError. Он пытается интерполировать то же самое странное сочетание символов в сообщение об ошибке и терпит неудачу. Если вы выясните, почему это происходит, вам на самом деле не понадобится пользовательская команда загрузки.   -  person Peter DeGlopper    schedule 30.10.2013
comment
@PeterDeGlopper Спасибо, это очень полезно.   -  person Marcin    schedule 30.10.2013
comment
Что же касается того, что происходит... это очень странно. Запросы к другим таблицам, если они есть, показывают ту же ошибку? Есть ли в базе данных данные, которые могли быть получены из другого источника? Я бы, вероятно, попытался создать новую пустую базу данных sqlite, позволить syncdb создать таблицы и попробовать импортировать туда. По крайней мере, это помогло бы определить, есть ли что-то не так с вашей существующей базой данных.   -  person Peter DeGlopper    schedule 30.10.2013
comment
@PeterDeGlopper Верно, это по крайней мере звучит как направление поиска.   -  person Marcin    schedule 30.10.2013
comment
@PeterDeGlopper Каждая таблица, которую я проверял, кажется, подвержена одной и той же проблеме.   -  person Marcin    schedule 30.10.2013
comment
@PeterDeGlopper Оказывается, свежие базы данных подвержены той же проблеме. Помимо устранения содержимого базы данных как проблемы, я действительно не уверен, что вызывает это.   -  person Marcin    schedule 30.10.2013
comment
Странный. Вы используете версию sqlite3 для Python? Что возвращает python -c 'import sqlite3; print sqlite3.__file__'?   -  person Austin Phillips    schedule 30.10.2013
comment
@AustinPhillips Спасибо - мне было интересно, как это проверить. Результат /usr/lib/python2.7/sqlite3/__init__.pyc. Я собираюсь поискать и убедиться, что у меня нет двух разных версий Python (что возможно из-за путаницы с обновлением).   -  person Marcin    schedule 30.10.2013
comment
FWIW Я получаю тот же путь в системе Debian. Общий объект .so sqlite, который используется python -c 'import _sqlite3; print _sqlite3.__file__', — это /usr/lib/python2.7/lib-dynload/_sqlite3.so.   -  person Austin Phillips    schedule 31.10.2013
comment
@AustinPhillips Спасибо за вашу помощь. Я совершенно уверен, что это была нечестивая смесь версий, которая сделала это со мной.   -  person Marcin    schedule 07.11.2013


Ответы (1)


Это почти наверняка было вызвано тем, что у меня было две разные версии Python. После того, как я очистил существующий python и переустановил его из исходного кода, все работает как надо.

Для тех, кто хочет перекомпилировать из исходников:

  1. Redhat компилируется с включенным UCS-4, в отличие от UCS-2 по умолчанию. Вероятно, вы захотите настроить что-то вроде ./configure --prefix=/usr --enable-shared --enable-unicode=ucs4.
  2. У Python много зависимостей. Команды менеджера пакетов здесь, вероятно, самый простой способ выяснить, что вам не хватает: http://docs.python.org/devguide/setup.html‎.
  3. Помните, что если вы используете virtualenv, ваша среда, скорее всего, не улавливает изменения в вашем глобальном python.
person Marcin    schedule 06.11.2013