我的類包含一個連接到服務器的套接字。該類的某些方法可能會拋出異常。我正在運行的腳本包含一個外部循環,用於捕獲異常,記錄錯誤並創建一個嘗試重新連接到服務器的新類實例。當你拋出異常時,python對象會發生什麼變化
問題是服務器一次只處理一個連接(按設計)並且「舊」套接字仍處於連接狀態。所以新的連接嘗試掛起腳本。我可以通過強制關閉舊套接字來解決這個問題,但我想知道:爲什麼套接字不能自動關閉?
當它「卡住」時,netstat會顯示連接到端口的兩個套接字。服務器正在等待來自第一個套接字的輸入,但它尚未處理新的套接字。
我對虛擬服務器執行此操作,該虛擬服務器向每個傳入線路回覆「error \ n」。
編輯:請參閱我對Mark Rushakoff's answer below的評論。從異常處理程序中斷言[錯誤] [我隨後捕獲]似乎強制套接字關閉。
import socket
class MyException(Exception):
pass
class MyClient(object):
def __init__(self, port):
self.sock = socket.create_connection(('localhost', port))
self.sockfile = self.sock.makefile()
def do_stuff(self):
self._send("do_stuff\n")
response = self._receive()
if response != "ok\n":
raise MyException()
return response
def _send(self, cmd):
self.sockfile.write(cmd)
self.sockfile.flush()
def _receive(self):
return self.sockfile.readline()
def connect():
c = MyClient(9989)
# On the second iteration, do_stuff() tries to send data and
# hangs indefinitely.
print c.do_stuff()
if __name__ == '__main__':
for _ in xrange(3):
try:
connect()
except MyException, e:
print 'Caught:', e
# This would be the workaround if I had access to the
# MyClient object:
#c.sock.close()
#c.sockfile.close()
編輯:這裏的(醜陋的)服務器代碼:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
s.bind(('localhost', 9989))
s.listen(5)
(c,a) = s.accept()
f = c.makefile()
print f.readline()
f.write('error\n')
f.flush()
(c2,a) = s.accept()
f = c.makefile()
print f.readline()
s.close()
我不確定這是否有水。我剛剛發現,如果我將try /除了在另一個try/except除AssertionError外並且在內部的except塊中斷言(False),那麼套接字就會被清除。我懷疑它與持有對該對象的引用並因此引用套接字的異常堆棧跟蹤有關? – bstpierre 2009-09-25 02:57:10
你的例子不是一個完整的程序(服務器代碼沒有提供),所以有點難以確認這方面的行爲。 – 2009-09-25 03:01:01
感謝您添加變通方法。我沒有解決它的問題,我只是想了解什麼是對象的引用......現在我必須假設它是追溯。 – bstpierre 2009-09-25 03:03:35