这个问题的简短答案是:如果发生任何异常(包括KeyboardInterrupt和),请求将关闭连接SystemExit。一个小 挖入请求的源代码显示,requests.get最终调用的HTTPAdapter.send方法(这是所有魔术发生)。在该send方法内可以通过两种方式发出请求:分块或不分块。其中send我们执行要看的价值request.body和Content-Length标题:chunked = not (request.body is None or 'Content-Length' in request.headers)在请求主体为None或的情况下Content-Length,requests将使用以下高级urlopen方法urllib3:if not chunked: resp = conn.urlopen( method=request.method, url=url, body=request.body, # ... )该方法的finally块urllib3.PoolManager.urlopen具有在try块未成功执行的情况下处理关闭连接的代码:clean_exit = False# ...try: # ... # Everything went great! clean_exit = Truefinally: if not clean_exit: # We hit some kind of exception, handled or otherwise. We need # to throw the connection away unless explicitly told not to. # Close the connection, set the variable to None, and make sure # we put the None back in the pool to avoid leaking it. conn = conn and conn.close() release_this_conn = True在响应可以分块的情况下,请求会降低一点并使用由提供的底层低层连接urllib3。在这种情况下,请求仍会处理异常,它使用try/except块执行此操作,该块在获取连接后立即开始,并以:low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT)try: # ...except: # If we hit any problems here, clean up the connection. # Then, reraise so that we can handle the actual exception. low_conn.close() raise有趣的是,如果没有错误,则连接可能不会关闭,具体取决于您为组态连接池的方式urllib3。在成功执行的情况下,将连接放回连接池中(尽管我无法_put_conn在requests源代码中找到针对chunked的调用send,这可能是在chunked工作流程中的错误)。