我正在使用需要查詢PostgreSQL數據庫的Django Web應用程序。當使用Python threading接口實現併發時,我得到DoesNotExist
錯誤的查詢項目。當然,順序執行查詢時不會發生這些錯誤。使用線程時Django中的數據庫錯誤
讓我告訴一個單元測試,我寫了證明意外的行爲:
class ThreadingTest(TestCase):
fixtures = ['demo_city',]
def test_sequential_requests(self):
"""
A very simple request to database, made sequentially.
A fixture for the cities has been loaded above. It is supposed to be
six cities in the testing database now. We will made a request for
each one of the cities sequentially.
"""
for number in range(1, 7):
c = City.objects.get(pk=number)
self.assertEqual(c.pk, number)
def test_threaded_requests(self):
"""
Now, to test the threaded behavior, we will spawn a thread for
retrieving each city from the database.
"""
threads = []
cities = []
def do_requests(number):
cities.append(City.objects.get(pk=number))
[threads.append(threading.Thread(target=do_requests, args=(n,))) for n in range(1, 7)]
[t.start() for t in threads]
[t.join() for t in threads]
self.assertNotEqual(cities, [])
正如你所看到的,第一個測試順序執行一些數據庫請求,這確實是沒有問題的工作。然而,第二個測試執行完全相同的請求,但每個請求都在一個線程中產生。這實際上是失敗的,返回一個DoesNotExist
異常。
的這個單元測試執行的輸出是這樣的:
test_sequential_requests (cesta.core.tests.threadbase.ThreadingTest) ... ok
test_threaded_requests (cesta.core.tests.threadbase.ThreadingTest) ...
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/jose/Work/cesta/trunk/src/cesta/core/tests/threadbase.py", line 45, in do_requests
cities.append(City.objects.get(pk=number))
File "/home/jose/Work/cesta/trunk/parts/django/django/db/models/manager.py", line 132, in get
return self.get_query_set().get(*args, **kwargs)
File "/home/jose/Work/cesta/trunk/parts/django/django/db/models/query.py", line 349, in get
% self.model._meta.object_name)
DoesNotExist: City matching query does not exist.
...其他線程返回一個類似的輸出...
Exception in thread Thread-6:
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/jose/Work/cesta/trunk/src/cesta/core/tests/threadbase.py", line 45, in do_requests
cities.append(City.objects.get(pk=number))
File "/home/jose/Work/cesta/trunk/parts/django/django/db/models/manager.py", line 132, in get
return self.get_query_set().get(*args, **kwargs)
File "/home/jose/Work/cesta/trunk/parts/django/django/db/models/query.py", line 349, in get
% self.model._meta.object_name)
DoesNotExist: City matching query does not exist.
FAIL
======================================================================
FAIL: test_threaded_requests (cesta.core.tests.threadbase.ThreadingTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jose/Work/cesta/trunk/src/cesta/core/tests/threadbase.py", line 52, in test_threaded_requests
self.assertNotEqual(cities, [])
AssertionError: [] == []
----------------------------------------------------------------------
Ran 2 tests in 0.278s
FAILED (failures=1)
Destroying test database for alias 'default' ('test_cesta')...
請記住,這一切都是發生在PostgreSQL數據庫中,該數據庫應該是線程安全的,而不是SQLite或類似的。測試也使用PostgreSQL進行。
在這一點上,我完全失去了什麼可以失敗。任何想法或建議?
謝謝!編輯:
編輯:我寫了一個小視圖,只是爲了檢查它是否能用於測試。下面是這個視圖的代碼:
def get_cities(request):
queue = Queue.Queue()
def get_async_cities(q, n):
city = City.objects.get(pk=n)
q.put(city)
threads = [threading.Thread(target=get_async_cities, args=(queue, number)) for number in range(1, 5)]
[t.start() for t in threads]
[t.join() for t in threads]
cities = list()
while not queue.empty():
cities.append(queue.get())
return render_to_response('async/cities.html', {'cities': cities},
context_instance=RequestContext(request))
(請不要考慮寫視圖代碼中的應用程序邏輯的愚蠢記住,這只是一個概念證明,並不會是永遠在真實應用程序中)
結果是代碼運行良好,請求在線程中成功完成,視圖最終在調用其URL後顯示城市。
因此,我認爲使用線程進行查詢只會在您需要測試代碼時出現問題。在生產中,它將毫無問題地工作。
任何有用的建議,測試這種類型的代碼成功?
您確定導入燈具嗎?你可以粘貼這樣的日誌:「Fixture demo_city processed」或類似的東西......啊,沒關係..只是沒有看完整個問題。 – Tisho