在另一个模块中捕获异常时如何处理异常

How to handle an exception when it is catched in a another module

它们是防止模块 urllib3 捕获键盘中断的方法吗? 当 KeyboardInterrupt 发生时,我需要执行一些处理,但问题是 urllib3 模块似乎捕获异常而不传递它。

我写了一个示例脚本来演示我的问题。

connector.py

import requests
from time import sleep

class Connector:
    def __init__(self):
        pass

    def connect(self):
        try:
            URL="https://www.gelbeseiten.de"
            print("Connecting")
            sleep(1)
            print("Now")
            requests.get(URL)
            requests.get(URL)
            requests.get(URL)
            requests.get(URL)
        except Exception as e:
            print("Exception in connect")
            raise Exception()

main.py

import connector

def main():
    try:
        conn=connector.Connector()
        conn.connect()
    except Exception as e:
        print("Exception in main")

if __name__ == '__main__':
    main()

如果脚本正在执行 GET 请求,我会执行 KeyboardInterrupt (Ctrl + C),我期望的是先打印“连接异常”,然后打印“主异常”,但我得到以下信息输出

Traceback (most recent call last):
  File "/tmp/test/main.py", line 11, in <module>
    main()
  File "/tmp/test/main.py", line 6, in main
    conn.connect()
  File "/tmp/test/connector.py", line 16, in connect
    requests.get(URL)
  File "/usr/lib/python3/dist-packages/requests/api.py", line 76, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/lib/python3/dist-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 428, in __exit__
    self.close()
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 747, in close
    v.close()
  File "/usr/lib/python3/dist-packages/requests/adapters.py", line 325, in close
    self.poolmanager.clear()
  File "/usr/lib/python3/dist-packages/urllib3/poolmanager.py", line 222, in clear
    self.pools.clear()
  File "/usr/lib/python3/dist-packages/urllib3/_collections.py", line 100, in clear
    self.dispose_func(value)
  File "/usr/lib/python3/dist-packages/urllib3/poolmanager.py", line 173, in <lambda>
    self.pools = RecentlyUsedContainer(num_pools, dispose_func=lambda p: p.close())
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 491, in close
    if conn:
KeyboardInterrupt

这表明模块 urllib3 收到了中断信号,但没有将其传递给我的异常处理程序。他们是获得我预期行为的一种方式吗?

KeyboardInterrupt不会被抓到

exception KeyboardInterrupt Raised when the user hits the interrupt key (normally Control-C or Delete). During execution, a check for interrupts is made regularly. The exception inherits from BaseException so as to not be accidentally caught by code that catches Exception and thus prevent the interpreter from exiting.

https://docs.python.org/3/library/exceptions.html#KeyboardInterrupt

这里的问题是 KeyboardInterrupt 不是 Exception 的子类。如果你特别想捕捉KeyboardInterrupt,你必须使用except KeyboardInterrupt as e:.

此外,最好使用raise e而不是提出新的Exception

我认为您需要更改 raise 脚本,因为 KeyboardInterrupt 似乎不像是从 Exception 继承的。相反,它来自 BaseException。 请为您的 connector.py.

尝试以下代码
import requests
from time import sleep

class Connector:
    def __init__(self):
        pass

    def connect(self):
        try:
            URL="https://www.gelbeseiten.de"
            print("Connecting")
            sleep(1)
            print("Now")
            requests.get(URL)
            requests.get(URL)
            requests.get(URL)
            requests.get(URL)
        except Exception as e:
            print("Exception in connect")
            raise Exception()
        except KeyboardInterrupt as e:
            print("Keyboard interrupt")
            raise Exception