Friday, January 8, 2016

sqlite3 “OperationalError: no such table” on threaded operation

from django.db import models

# Super-simple model
class MyModel(models.Model):
message = models.CharField('Message', max_length=200, blank=True)

#Test
from django.test import TestCase

import time
import threading
import random


done = threading.Event()
nThreads = 1


def InsertRec(msg):
rec = MyModel.objects.create(message=msg)
rec.save()


def InsertThread():
try:
msgNum = 1
thrName = threading.currentThread().name
print 'Starting %s' % thrName
while not done.wait(random.random() * 0.1):
msgNum += 1
msg = '%s: %d' % (thrName, msgNum)
print msg
InsertRec(msg)
finally:
done.set()
pass


class ThreadTestRun(TestCase):

def testRunIt(self):
nThisThread = 10
msgSet = set()
for x in xrange(nThisThread):
msg = 'Some message %d' % x
InsertRec(msg) # From main thread: works!
msgSet.add(msg)
self.assertEqual(MyModel.objects.count(), nThisThread)
# We use sets because .all() doesn't preserve the original order.
self.assertEqual(msgSet, set([r.message for r in MyModel.objects.all()]))
thrSet = set()
for thrNum in xrange(nThreads):
t = threading.Thread(name='Thread %d' % thrNum, target=InsertThread)
t.start()
thrSet.add(t)

done.wait(10.)
done.set()
for t in thrSet:
t.join()


By everything I read in the docs, both Django and py-sqlite3 should be fine with threaded access. (Right?) But the attached code snippet fails for me. The operations in the main thread work, but not in the thread(s) I create. There I get:

File "C:\Python27\lib\site-packages\django-1.9-py2.7.egg\django\db\backends\sq lite3\base.py", line 323, in execute return Database.Cursor.execute(self, query, params)

OperationalError: no such table: thrtest_mymodel

What's the problem?


How do I go about tracking down exactly what's happening? The point of failure in Django is pretty indimidating. I can't tell how to see what tables it DOES see, or what differences to look for between main and other threads.


Here is DATABASES from settings.py:

DATABASES = {      'default': {          'ENGINE': 'django.db.backends.sqlite3',          'NAME': ':memory:', # os.path.join(BASE_DIR, 'db.sqlite3'),          'TEST_NAME' : ':memory:',      },  }


With respect to Django's ticket #12118, I get the same symptoms using ':memory:' or a disk file (for TEST_NAME).


Django 1.9, Python 2.7.11.


Posted yesterday on stackoverflow.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/9409d2f4-5530-4261-b501-c6833f39c735%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment