在runInteraction()中scrapy mysql管道临界区

时间:2012-07-11 12:54:13

标签: python multithreading twisted scrapy mysql-python

我需要帮助修复管道scrapy代码中的关键部分。

我在scrapy中使用这个MySQL管道(来自http://snippets.scrapy.org/snippets/33/):

class SQLStorePipeline(object):

def __init__(self):
    self.dbpool = adbapi.ConnectionPool('MySQLdb', db='mydb',
            user='myuser', passwd='mypass', cursorclass=MySQLdb.cursors.DictCursor,
            charset='utf8', use_unicode=True)

def process_item(self, item, spider):
    # run db query in thread pool
    query = self.dbpool.runInteraction(self._conditional_insert, item)
    query.addErrback(self.handle_error)

    return item

def _conditional_insert(self, tx, item):
    # create record if doesn't exist. 
    # all this block run on it's own thread


    # START CRITICAL SECTION
    some_critical_code_here
    # STOP CRITICAL SECTION


    tx.execute("select * from websites where link = %s", (item['link'][0], ))
    result = tx.fetchone()
    if result:
        log.msg("Item already stored in db: %s" % item, level=log.DEBUG)
    else:
        tx.execute(\
            "insert into websites (link, created) "
            "values (%s, %s)",
            (item['link'][0],
             datetime.datetime.now())
        )
        log.msg("Item stored in db: %s" % item, level=log.DEBUG)

def handle_error(self, e):
    log.err(e)

一切正常。

正如您所看到的,我已经知道代码中的关键部分在哪里。但是我对python 非常陌生,不知道如何使用某些锁或类似之类的东西来防止通过更多的线程进入crical部分。

你能帮帮我吗? 如果您可以向我发送输入和离开我可以在此代码中使用的关键部分的代码,那将非常棒。

Thx家伙。

2 个答案:

答案 0 :(得分:1)

即使您正在使用Twisted,通常所有涉及阻塞的内容都需要以不同的方式完成,您仍然处于Twisted的特定部分,其中阻塞是可以的。所以这应该像分配一个所有线程都能够引用的Lock对象一样简单,然后获取它:

import threading

insert_critical_lock = threading.Lock()

...

def _conditional_insert(self, tx, item):

    with insert_critical_lock:
        # START CRITICAL SECTION
        some_critical_code_here
        # STOP CRITICAL SECTION

    tx.execute("select * from websites where link = %s", (item['link'][0], ))
    ...

答案 1 :(得分:0)

无论如何,我通过合并临界区中的sql语句来解决它 对于这个想法,在scrapy IRC上使用nick toothrot的人