我创建了一个方法,从一个网页下载产品,然后将该产品存储到数据库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,因此不应该出现并发问题,但结果相同 - 数据库中没有新行。
答案 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)。
第一个解决方案是确认我展示的任务,以便使问题可见。然后你可以做的是为每个工人获得一个专用光标。