Django应用中的线程处理

2 投票
4 回答
4145 浏览
提问于 2025-04-15 17:57

我正在尝试创建一个我称之为“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 个回答

1

这就需要一个任务队列,但不一定要用线程。你会有一个服务器进程,还有一个或多个记录进程,以及一个让它们可以互相交流的队列。这个队列可以放在数据库里,也可以用其他的东西,比如 beanstalkd。总之,这些和你的错误没关系,听起来你的数据库配置有问题。

1

1) 如果你换成一个真正的数据库,而不是SQLite,这个错误还会出现吗?

2) 如果你在使用线程,可能需要为每个线程创建独立的SQL游标。

2

在Django中,你不能在内存数据库(比如sqlite3)中使用多线程,具体可以参考这个问题。不过,如果你用PostgreSQL或MySQL,可能就没问题了。

我建议你使用像celeryd这样的工具,而不是多线程。消息队列比多线程要简单得多,使用起来更方便。

撰写回答