在django app中线程化

时间:2010-01-12 20:47:21

标签: python django multithreading

我正在努力创造我称之为scrobbler的东西。任务是从队列中读取Delicious用户,获取所有书签并将其放入书签队列。然后应该通过该队列,进行一些解析,然后将数据存储在数据库中。

这显然需要线程化,因为大多数时间花在等待Delicious响应,然后用于书签的网站响应并通过某些API传递,所有事情等待它都是愚蠢的。

但是我遇到了线程问题,并且一直没有定义数据库表等奇怪的错误。任何帮助表示赞赏:)

以下是相关代码:

# relevant model #
class Bookmark(models.Model):
 account = models.ForeignKey( Delicious )
 url = models.CharField( max_length=4096 )
 tags = models.TextField()
 hash = models.CharField( max_length=32 )
 meta = models.CharField( max_length=32 )

# bookmark queue reading #
def scrobble_bookmark(account):
 try:
  bookmark = Bookmark.objects.all()[0]
 except Bookmark.DoesNotExist:
  return False

 bookmark.delete()

 tags = bookmark.tags.split(' ')
 user = bookmark.account.user

 for concept in Concepts.extract( bookmark.url ):
  for tag in tags:
   Concepts.relate( user, concept['name'], tag )

 return True

def scrobble_bookmarks(account):
 semaphore = Semaphore(10)
 for i in xrange(Bookmark.objects.count()):
  thread = Bookmark_scrobble(account, semaphore)
  thread.start()

class Bookmark_scrobble(Thread):
 def __init__(self, account, semaphore):
  Thread.__init__(self)
  self.account = account
  self.semaphore = semaphore

 def run(self):
  self.semaphore.acquire()
  try:
   scrobble_bookmark(self.account)
  finally:
   self.semaphore.release()

这是我得到的错误:

Exception in thread Thread-65:
Traceback (most recent call last):
  File "/usr/lib/python2.6/threading.py", line 525, in __bootstrap_inner
    self.run()
  File     "/home/swizec/Documents/trees/bookmarklet_server/../bookmarklet_server/Scrobbler/Scrobbler.py", line 60, in run
    scrobble_bookmark(self.account)
  File     "/home/swizec/Documents/trees/bookmarklet_server/../bookmarklet_server/Scrobbler/Scrobbler.py", line 28, in scrobble_bookmark
    bookmark = Bookmark.objects.all()[0]
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 152, in __getitem__
    return list(qs)[0]
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 76, in __len__
self._result_cache.extend(list(self._iter))
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 231, in iterator
    for row in self.query.results_iter():
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 281, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 2373, in execute_sql
cursor.execute(sql, params)
  File "/usr/local/lib/python2.6/dist-packages/django/db/backends/sqlite3/base.py", line 193, in execute
    return Database.Cursor.execute(self, query, params)
OperationalError: no such table: Scrobbler_bookmark

PS:所有其他测试取决于相同的表格,并以漂亮的颜色传递。

4 个答案:

答案 0 :(得分:2)

你不能在Django的内存数据库(在本例中为sqlite3)中使用线程,请参阅此bug。这可能适用于PostgreSQL或MySQL。

我建议使用celeryd而不是线程,消息队列比线程更容易使用。

答案 1 :(得分:1)

这需要一个任务队列,但不一定是线程。您将拥有服务器进程,一个或多个scrobbler进程以及允许它们进行通信的队列。队列可以在数据库中,也可以像beanstalkd那样分开。所有这些都与您的错误无关,这听起来像您的数据库错误配置。

答案 2 :(得分:1)

1)如果使用真实数据库而不是SQLite,错误是否仍然存在?

2)如果您正在使用线程,则可能需要创建单独的SQL游标以供线程使用。

答案 3 :(得分:0)

我认为该表确实不存在,所以必须首先由SQL commad创建它 或任何其他方式。因为我有一个用于测试不同模块的小型数据库,我只是删除 数据库并使用syncdb命令重新创建它