我使用Jupyter Notebook来处理存储在django / postgres中的数据。我以这种方式初始化我的项目:
sys.path.append('/srv/gr/prg')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'prg.settings')
if 'setup' in dir(django):
django.setup()
有许多更新数据的单独进程,我想对其进行多线程处理以加快进程。当我在单个线程中进行更新或使用sqlite
时,一切工作都很好。
def extract_org_description(id):
o = models.Organization.objects.get(pk=id)
logging.info("Looking for description for %s" % o.symbol)
try:
content = open('/srv/data/%s.html' % o.symbol)
except FileNotFoundError:
logging.error("HTML file not found for %s" % o.symbol)
return
doc = BeautifulSoup(content, 'html.parser')
desc = doc.select("#cr_description_mod > div.cr_expandBox > div.cr_description_full.cr_expand")
if not desc or not desc[0]:
logging.info("Cannot not find description for %s" % o.symbol)
return
o.description = desc[0].text
o.save(update_fields=['description'])
logging.info("Description for %s found" % o.symbol)
return("done %s" % id)
这将不起作用:
p = Pool(2)
result = p.map(extract_org_description, orgs)
print(result)
在大多数情况下,它会挂起,直到我中断它为止,而没有任何特定错误,有时postgres将出现“已有事务正在进行中”,有时我看到“没有要提取的结果”错误。试着使用池的大小,我可以使其工作一次或两次,但是很难诊断出到底是什么问题。
我尝试更改策略以选择对象并将其映射到将对象作为参数的extract_org_description
(与基于键选择不同),但这并没有更好的效果。
我唯一想到的是,当django尝试自动提交时,所有单独的更新(包括在其他线程中发生的更新)都在同一事务范围内,这引起了问题。但是我不知道如何在Django中解决这个问题。
答案 0 :(得分:1)
您的问题包括 multiprocessing 和 multithread 术语,但重要的是要了解它们是实现并发的不同方法。
Django具有对多线程的内置支持,并且将create a new database connection for each thread。如果从多处理切换到多线程,则应该解决问题。
在多处理中,整个过程是分叉的,新过程将具有与旧过程相同的数据库连接。这就导致了您所看到的问题,例如,当另一个进程已经在同一数据库连接上打开一个新事务时,您尝试打开一个新事务。
如果您确实需要多处理而非多线程,则可能有解决方案。例如,this answer建议仅关闭数据库连接,迫使Django创建新的连接。