我建议你在线程中使用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)
这对我来说非常有效。用于挂起连接或正在进行的传输。
可能仍然存在一些警告或错误,最好说是错误,需要修复。