从池修改数据库不起作用(但没有例外)

时间:2015-10-18 11:15:11

标签: python sqlite cursor threadpool python-multiprocessing

我创建了一个方法,从一个网页下载产品,然后将该产品存储到数据库SQLite3中。

这个函数在正常调用时效果很好但是我想创建一个池并且并行执行(因为发送并行请求)(网页允许机器人发送2000个请求/分钟)。

问题在于,当我尝试将其放入池中时,它不会将数据存储到数据库中,也不会引发一些error or exception

这是主要功能的代码:

if __name__ == '__main__':
    pu = product_updater() # class which handles almost all, this class also has database manager class as an attribute
    pool = Pool(10) 

    for line in lines[0:100]: # list lines is a list of urls
        # pu.update_product(line[:-1]) # this works correctly 
        pool.apply_async(pu.update_product, args=(line[:-1],)) # this works correctly but does not store products into the database

    pool.close()
    pool.join()

def update_product(self,url): # This method belongs to product_updater class

    prod = self.parse_product(url)
    self.man.insert_product(prod) # man is a class to handling database

我使用此池:from multiprocessing.pool import ThreadPool as Pool

你知道可能出现什么问题吗?

编辑:我认为这可能是因为只有一个光标在工作人员之间共享,但我认为如果这是一个问题,它会引发一些Exception

EDIT2:奇怪的是我尝试创建只有1个worker的Pool,因此不应该出现并发问题,但结果相同 - 数据库中没有新行。

1 个答案:

答案 0 :(得分:1)

multiprocessing.Pool不会通知工作人员中发生的异常,只要您不要求任务确认。

这个例子将是沉默的。

from multiprocessing import Pool


def function():
    raise Exception("BOOM!")


p = Pool()
p.apply_async(function)
p.close()
p.join()

此示例将显示异常。

from multiprocessing import Pool


def function():
    raise Exception("BOOM!")


p = Pool()
task = p.apply_async(function)
task.get()  # <---- you will get the exception here
p.close()
p.join()

您的问题的根本原因是共享单个游标对象,该对象不是线程/进程安全的。当多个工作人员在相同的光标上读/写时,事情就会被破坏,而池会默默地吃掉例外(om nom)。

第一个解决方案是确认我展示的任务,以便使问题可见。然后你可以做的是为每个工人获得一个专用光标。