Python:如果脚本在 requests.get() 执行时停止会怎样?
Python: What happens if script stops while requests.get() is executing?
我知道 requests.get()
提供了一个 HTTP 接口,以便程序员可以向 HTTP 服务器发出各种请求。
这告诉我必须在某处打开一个端口才能发生请求。
考虑到这一点,如果脚本在请求 answered/complete 之前停止(例如,通过键盘中断,因此执行脚本的机器仍然连接到互联网)会发生什么?
port/connection会保持打开状态吗?
port/connection是否自动关闭?
问题的简短回答是:请求将在任何异常情况下关闭连接,包括KeyboardInterrupt
和SystemExit
。
一个little digging into the requests source code reveals that requests.get
ultimately calls the HTTPAdapter.send
方法(所有魔法都在这里发生)。
在 send
方法中可以通过两种方式发出请求:分块或不分块。我们执行哪个 send
取决于 request.body
和 Content-Length
header:
的值
chunked = not (request.body is None or 'Content-Length' in request.headers)
在请求body为None
或设置Content-Length
的情况下,requests
将make use of the high-level urlopen
方法urllib3
:
if not chunked:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
# ...
)
urllib3.PoolManager.urlopen
方法的 finally
块具有在 try
块未成功执行的情况下处理关闭连接的代码:
clean_exit = False
# ...
try:
# ...
# Everything went great!
clean_exit = True
finally:
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
提供的底层低级别连接。在这种情况下,requests 仍然处理异常,它使用 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
配置连接池的方式。在成功执行的情况下,连接被放回连接池(虽然我在 requests
源中找不到 _put_conn
调用分块 send
,这可能是一个分块 work-flow).
中的错误
在低得多的级别上,当程序退出时,OS 内核会关闭该程序打开的所有文件描述符。其中包括网络套接字。
我知道 requests.get()
提供了一个 HTTP 接口,以便程序员可以向 HTTP 服务器发出各种请求。
这告诉我必须在某处打开一个端口才能发生请求。
考虑到这一点,如果脚本在请求 answered/complete 之前停止(例如,通过键盘中断,因此执行脚本的机器仍然连接到互联网)会发生什么?
port/connection会保持打开状态吗?
port/connection是否自动关闭?
问题的简短回答是:请求将在任何异常情况下关闭连接,包括KeyboardInterrupt
和SystemExit
。
一个little digging into the requests source code reveals that requests.get
ultimately calls the HTTPAdapter.send
方法(所有魔法都在这里发生)。
在 send
方法中可以通过两种方式发出请求:分块或不分块。我们执行哪个 send
取决于 request.body
和 Content-Length
header:
chunked = not (request.body is None or 'Content-Length' in request.headers)
在请求body为None
或设置Content-Length
的情况下,requests
将make use of the high-level urlopen
方法urllib3
:
if not chunked:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
# ...
)
urllib3.PoolManager.urlopen
方法的 finally
块具有在 try
块未成功执行的情况下处理关闭连接的代码:
clean_exit = False
# ...
try:
# ...
# Everything went great!
clean_exit = True
finally:
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
提供的底层低级别连接。在这种情况下,requests 仍然处理异常,它使用 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
配置连接池的方式。在成功执行的情况下,连接被放回连接池(虽然我在 requests
源中找不到 _put_conn
调用分块 send
,这可能是一个分块 work-flow).
在低得多的级别上,当程序退出时,OS 内核会关闭该程序打开的所有文件描述符。其中包括网络套接字。