TestProcess = ProcessPoolExecutor(max_workers=5)
TestProcessRet = TestProcess.submit(TestCount,1,2,3)
# 如果 TestProcess 池的任务抛出了异常,
if TestProcess.running() != True:
if TestProcess.done() == True:
if TestProcess.exception():
print(type(TestProcess.result()))
print(TestProcess.exception())
# 想把异常的内容转为 String 类型做处理,请教应该如何实现?
# 上面两种类型,似乎都无法直接获取内容?
1
oahebky 2020-07-15 17:48:14 +08:00
|
2
uti6770werty OP @oahebky 非常感谢大大的思路介绍,也感谢您在另外一贴的提点(刚刚才看到。。。)
大大的思路非常的好,try 能做到,效果达到了,略有不同,至于为什么,水平有限也不知道是怎么回事,但异常的内容已经能拿到 String 内容了。。。 ``` if exc_futures[i].running() != True: if exc_futures[i].done() == True: # 如果运行结果是 done() if exc_futures[i].exception(): try: _ = exc_futures[i].result() except Exception as e: print(len(str(e.__cause__))) ``` 直接: except RuntimeError as e: print(f'got you, exceptions of sub-process with msg: "{str(e)}"') 直接拿 e 是不会有内容的, 我的是 Python 3.6.6, |
3
uti6770werty OP 特此报告~@oahebky
|
4
oahebky 2020-07-16 15:09:36 +08:00
@uti6770werty
====== 回复: "直接拿 e 是不会有内容的" 如果你函数(子进程内)抛出的异常没有内容(如 `raise ValueError()`)自然 `str(e)` 是空的。 可以考虑使用 repr(e) 代替 str(e),内容更详细(不过得到的字符串有可能是多行的)。 这一部分说明你对异常怎么使用还没有仔细看过,推荐你看一下《 learning python 》(有中文版) 的异常一章(在整书靠后的位置)。 ============== 另外,至于为什么要用 `try: exc_futures[i].result() except Exception as e: print(f"Error: {str(e)}")` 这样的写法。 是我看到你这个问题去看 `concurent.futures` package 中 ProcessPoolExecutor 的源码实现来回答的。 简单总结就是 pool 中的子进程内部发生的异常,在执行 `.result()` 的时候,“被提升”到了调用的进程(父进程)上面,从异常输出看过去就像父进程发生异常一样。 这么做的好处有几点,最明显的一点就是异常消息提供的信息和普通的函数调用异常消息一致,比较好定位错误。 另外就是功能较复杂的情况下,可以自己定义异常类,然后子进程抛出,父进程可以捕获精细的异常类做处理,这一点随着对 python 使用的加深还有看看我前面说的那本书那一章,会知道怎么操作的。 |