亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在Python線程中中止/取消HTTP請求?

如何在Python線程中中止/取消HTTP請求?

莫回無 2023-12-09 15:47:38
我正在尋找中止/取消 Python 線程中的 HTTP 請求。我必須堅持使用線程。我無法使用 asyncio 或標準庫之外的任何內容。此代碼適用于套接字:"""Demo for Canceling IO by Closing the SocketWorks!"""import socketimport timefrom concurrent import futuresstart_time = time.time()sock = socket.socket()def read():    "Read data with 10 second delay."    sock.connect(('httpbin.org', 80))    sock.sendall(b'GET /delay/10 HTTP/1.0\r\n\r\n')    while True:        data = sock.recv(1024)        if not data:            break        print(data.decode(), end='')with futures.ThreadPoolExecutor() as pool:    future = pool.submit(read)    futures.wait([future], timeout=5)    sock.close()  # <-- Interrupt sock.recv(1024) in Thread:read().end_time = time.time()print(f'Duration: {end_time - start_time:.3f}')# Duration is ~5s as expected.在主線程中關閉套接字用于中斷執行器池線程中的recv()。HTTP 請求應該需要 10 秒,但我們只等待 5 秒,然后關閉套接字(有效地取消 HTTP 請求/響應)?,F在我嘗試使用 http.client:"""Demo for Canceling IO in Threads with HTTP ClientDoesn't work!"""import timefrom concurrent import futuresfrom http.client import HTTPConnectiondef get(con, url):    con.request('GET', url)    response = con.getresponse()    return responsestart_time = time.time()with futures.ThreadPoolExecutor() as executor:    con = HTTPConnection('httpbin.org')    future = executor.submit(get, con, '/delay/10')    done, not_done = futures.wait([future], timeout=5)    con.sock.close()end_time = time.time()print(f'Duration: {end_time - start_time:.3f}')# Duration is ~10s unfortunately.不幸的是,這里的總持續時間約為 10 秒。關閉套接字不會中斷客戶端中的recv_into()??磥砦易龀隽艘恍╁e誤的假設。如何從單獨的線程中斷 http 客戶端中使用的套接字?
查看完整描述

1 回答

?
DIEA

TA貢獻1820條經驗 獲得超2個贊

您所描述的是預期的有據可查的行為:

注意 close() 釋放與連接關聯的資源,但不一定立即關閉連接。如果要及時關閉連接,請在 close() 之前調用 shutdown()。

有關此行為的一些進一步詳細信息仍然可以在 CPython howto 文檔中找到:

嚴格來說,您應該在關閉套接字之前對其使用 shutdown 。關閉是對另一端套接字的建議。根據您傳遞的參數,它可能意味著“我不會再發送,但我仍然會聽”,或者“我不聽,很好的擺脫!”。然而,大多數套接字庫已經習慣了程序員忽略使用這一禮儀,通常關閉與 shutdown() 相同;關閉()。因此在大多數情況下,不需要顯式關閉。

有效使用 shutdown 的一種方法是使用類似 HTTP 的交換??蛻舳税l送請求,然后執行關閉(1)。這告訴服務器“該客戶端已完成發送,但仍然可以接收。” 服務器可以通過接收 0 字節來檢測“EOF”。它可以假設它具有完整的請求。服務器發送回復。如果發送成功完成,那么客戶端確實仍在接收。

Python 在自動關閉方面更進了一步,它表示當套接字被垃圾回收時,如果需要它會自動關閉。但依賴這一點是一個非常不好的習慣。如果您的套接字在沒有執行關閉的情況下就消失了,另一端的套接字可能會無限期地掛起,認為您只是速度慢。完成后請關閉套接字。

解決方案

關閉之前調用 shutdown。

例子

with futures.ThreadPoolExecutor() as executor:
    con = HTTPConnection('httpbin.org')
    future = executor.submit(get, con, '/delay/10')
    done, not_done = futures.wait([future], timeout=5)
    con.sock.shutdown()
    con.sock.close()


查看完整回答
反對 回復 2023-12-09
  • 1 回答
  • 0 關注
  • 226 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號