python线程池异常处理方案

背景

  • 随着数据量增多,业务中处理该类数据的模块需要从串行处理升级成多线程处理。
  • 原流程中只有部分流程需要多线程优化,而多线程的执行结果又为上层所需。
  • 需要并行化的流程中可能出现异常。
  • 选择的线程池为multiprocessing.pool.ThreadPool
  • python解释器:官方cpython,2.7.15

方案设计

ThreadPool类使用方法

from multiprocessing.pool import ThreadPool

# 创建一个线程池
pool_size = 4
thread_pool = ThreadPool(pool_size)

# 调用map方法,将会对迭代对象拆包并各自开启线程交由目标函数处理
pool_output = thread_pool.map(目标的函数,可迭代对象)

# 关闭线程,禁止新线程加入;随后主线程等待其结束
thread_pool.close()
thread_pool.join()
  • 官方文档只说明了map方法可以返回各个目标函数的结果,但却没有交待当线程抛出异常时会如何处理

简单设计一个会抛出异常的函数

def square_may_fail(num):
	"""
	本函数会计算并返回入参的平方,
	但当入参为10的倍数时抛出异常
	"""
	print(num)
	if num % 10 ==0:
		raise Exception('find 10 mutiple')
	else:
		return num ** 2

# 在这里所有线程都会运行(包括抛出异常的),但pool_output不存在
pool_output = thread_pool.map(square_may_fail, range(11))

print(pool_size)
  • 这种方案下无法得到任何有效返回值,且还需要在map的外层用try…except包住。如果对返回结果不敢兴趣,且不在乎中间运行的细节,可以采用这种方案。

最终方案

  • 上述方案无法满足掌控线程运行状态的需求。且线程运行时出现的异常尽可能在线程内捕获处理,因此采取以下方案
def square_may_fail(num):
	"""
	本函数会计算并返回入参的平方,
	但当入参为10的倍数时抛出异常
	"""
	print(num)
	try:
		if num % 10 ==0:
			raise Exception('find 10 mutiple')
		else:
			return num ** 2
	except Exception as e:
		return e
  • 这时候map方法能够正常返回所有线程的执行结果,在上层中根据结果作下一步处理。

版权声明:本文为qq_18122705原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。