gpt4 book ai didi

python - 当服务器没有响应时在 Python 中中止 GET 请求

转载 作者:可可西里 更新时间:2023-11-01 16:49:44 27 4
gpt4 key购买 nike

我已经在 Python 中实现了一个 HTTP 长轮询器。简单来说,它是一个定期连接到服务器并通过 GET 请求检索一些信息的程序。长轮询技术与“正常”轮询不同,因为如果服务器收到请求但没有新数据,它不会发送空响应,而是等待新数据可用,从而使请求保持打开状态。

基本上,当我向该服务器发出请求时,它可能会立即向我发送回复,或者它可能会使我的 GET 打开几分钟。

一切正常,当我想关闭我的程序时,问题出现了。我已经尝试了 urllib3requests 模块,如果有挂起的请求,它们不会让我的程序关闭。

所以,我的问题是,当服务器没有响应(使用提到的模块)时,是否有办法中止 GET 请求。在这些情况下,设置超时会解决我的问题,但在这种特定情况下显然是不可能的。

一个解决方案可能是将请求放在一个线程中,并在程序关闭时终止它,但终止线程并不是一个好的做法。也许有一个更明确的模块来实现长轮询?

最佳答案

我建议您在线程中使用 urllib2(我没有看到任何其他方式),然后在等待响应时关闭连接。

其他方法都可以解决问题,但不是您想要的那种感觉。

一个是你总是从服务器返回数据,但是当你没有信息要返回时,返回一些消息,表明客户端应该稍后再检查。

您提到的一个是终止线程,但是,这不是很好的解决方案。

我建议关闭与服务器的连接并等待它断开:

from urllib2 import urlopen
from thread import start_new_thread as thread
from time import sleep

class Req:
def __init__ (self, url, callback=lambda: None):
self.polled_conn = None
self.url = url
self.data = None
self.error = None
self.callback = callback
self.cancelled = 0
self.polling = 0

def poll (self):
thread(self._poll,())

def get (self):
self.data = None
self.error = None
cb = self.callback
self.callback = lambda: None
thread(self._poll,())
while self.data==None and self.error==None: sleep(0.001)
self.callback = cb
if self.error: raise self.error
return self.data

def _poll (self):
if self.polling: return
self.polling = 1
self.data = None
self.error = None
self.cancelled = 0
try:
self.polled_conn = u = urlopen(self.url)
except Exception, e: self.error = e; self.polling = 0; return self.callback()
try:
self.data = u.read()
except AttributeError, e:
if "recv" in str(e): self.cancelled = 1; self.polling = 0; return # Receiving aborted!
else: self.error = e
except IOError, e: self.cancelled = 1; self.polling = 0; return # Receiving aborted
except Exception, e: self.error = e
self.polling = 0
self.callback()

def cancel (self):
if self.polled_conn:
self.polled_conn.close()

def iscancelled (self): return self.cancelled

一些用法是通过 get() 方法提供的,但您没有更多的可能性。使用 get() 你有标准的数据阻塞返回:

r = Req("http://example.com")
data = r.get()
print data

为了实现你想要的,你可以在这里指定一个回调并用它来处理数据,在程序退出时你可以取消任何挂起的传输:

def oncallback ():
if r.data!=None:
print len(r.data), r.data[:100]
else: raise r.error
sleep(1)
r.poll() # Poll again for new info

r = None
def start ():
global r
r = Req("http://example.com", oncallback)
r.poll()

start()
raw_input() # Wait for enter to close
r.cancel()
print "Cancelling"
if r.polling:
while not r.iscancelled(): sleep(0.001)
print "Ready to close!"
# You can set r.polling to 1, to prevent the callback to poll again in midle of shutdown
#r.polling = 1 # Dirty trick
# Using threading module would make things just a little easier

或者您仍然可以在没有回调的情况下执行此操作(类似异步):

running = 1
r = Req("http://example.com")
r.poll()
while running:
if r.error!=None:
print r.error
# Decide what to do according to this error
#if not isinstance(r.error, URLError): r.poll() # or something
continue
if r.data==None: sleep(0.001); continue # Do something anyway while waiting for data
# Data arrived so:
print data[:100] # Do some stuff
r.poll() # Poll again for new
# Somewhere here check whether user wants to close a program and then
#running = 0 or break

r.cancel()
if r.polling:
while not r.iscancelled(): sleep(0.001)

这非常适合我。用于挂起连接或正在进行的传输。可能仍然存在一些警告或错误,更确切地说是错误,需要修复。

关于python - 当服务器没有响应时在 Python 中中止 GET 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31998421/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com