1

Django で失敗する簡単なテスト ケースがあります。

モデル (app/models.py):

from django.db import models
class M(models.Model):
    condition = models.CharField(max_length=80, db_index=True)

テスト (app/tests.py):

from django.test import TestCase
import threading
import time
from app.models import M

def insert():
    time.sleep(0.3)
    ua = M(condition='x')
    ua.save()

class DjangoRaceTest(TestCase):
    def test_parallel(self):
        insert()  # <--- works
        #threading.Thread(target=insert).start()  # <-- fails

        for i in range(10):
            count = M.objects.all()
            if count:
                return True
            time.sleep(0.1)

        assert count

上記のコードはパスします。しかし、insert への直接呼び出しをコメント アウトし、代わりにスレッド呼び出しのコメントを解除すると、アサーションは失敗し、次のようになります。

Creating test database for alias 'default'...
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.6/threading.py", line 532, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.6/threading.py", line 484, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/home/jacobsen/testdjango/app/tests.py", line 10, in insert
    ua.save()
  File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/base.py", line 463, in save
    self.save_base(using=using, force_insert=force_insert, force_update=force_update)
  File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/base.py", line 551, in save_base
    result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
  File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/manager.py", line 203, in _insert
    return insert_query(self.model, objs, fields, **kwargs)
  File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/query.py", line 1576, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/sql/compiler.py", line 910, in execute_sql
    cursor.execute(sql, params)
  File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/backends/sqlite3/base.py", line 337, in execute
    return Database.Cursor.execute(self, query, params)
DatabaseError: no such table: app_m

明らかに、ここで私を失敗させている Django の魔法がありますか、それとも...何か? OS X、Ubuntu 10.04、Django 1.2 および 1.4 のさまざまな組み合わせでこれをテストしました。

4

1 に答える 1

2

答えは、メモリ内のsqliteデータベースをスレッド間で共有できないということのようです。

これは1.1からのバグレポートであり、コア開発者はSQLAlchemyのサポートの欠如に基づいてバグではないと結論付けています(sqlite参照からの他の直接情報がない場合):

check_same_thread PysqliteフラグがFalseに設定されていない限り、Pysqlite接続はスレッド間の移動をサポートしていません。さらに、インメモリSQLiteデータベースを使用する場合、完全なデータベースは単一の接続のスコープ内にのみ存在します。インメモリデータベースは、check_same_threadフラグに関係なく、スレッド間での共有をサポートしていないことが報告されています。つまり、接続へのアクセスが単一のワーカーに制限されていない限り、マルチスレッドアプリケーションはスレッド間で:memory:データベースからのデータを共有できません。キューイングメカニズムを介して同時スレッドと通信するスレッド。

于 2012-06-26T19:09:35.410 に答える