V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
uti6770werty
V2EX  ›  Python

琢磨不出来就问,请教 concurrent.futures 并行,进程抛出异常后,如何获取异常消息为 String?

  •  
  •   uti6770werty · 2020-07-11 10:59:58 +08:00 · 444 次点击
    这是一个创建于 1383 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 类型做处理,请教应该如何实现?
                # 上面两种类型,似乎都无法直接获取内容?
    
    4 条回复    2020-07-16 15:09:36 +08:00
    oahebky
        1
    oahebky  
       2020-07-15 17:48:14 +08:00
    了解一下:

    https://paste.ubuntu.com/p/zJmWshSnjZ/


    👆 看看是不是你想要的效果。
    uti6770werty
        2
    uti6770werty  
    OP
       2020-07-16 12:59:59 +08:00
    @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,
    uti6770werty
        3
    uti6770werty  
    OP
       2020-07-16 13:00:32 +08:00
    特此报告~@oahebky
    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 使用的加深还有看看我前面说的那本书那一章,会知道怎么操作的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3014 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 871ms · UTC 00:31 · PVG 08:31 · LAX 17:31 · JFK 20:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.