sys.exit()没有在python中退出

时间:2015-03-26 11:18:12

标签: python multithreading sockets

我有一个使用socketSocketServer的python2程序。它基本上由一些可以相互连接的客户端组成。每个客户端也有自己的Thread,它使用threading.Thread实现并以daemon模式运行。现在我的问题是,当我调用sys.exit()时,程序不会退出。我也会(尝试)在sys.exit()调用之前关闭所有打开的套接字。我也在程序中使用socket.makefile(),但是,在我读完所有已打开的文件之后,我会立即调用close。如果sys.exit()没有退出,可能是什么原因?

这是代码,应用程序应该代表节点图, 如果我们在第一个节点上用第二个节点的地址调用initiateConnection,每个节点将包含一个Edge到另一个节点。由于边缘是无向的,我希望套接字的两边都由相同的{{1}处理请参阅上面的注释RequestHandler

Client.initiateConnection

UPDATE :我已经确定了(相当明显的)问题,句柄方法永远不会退出循环,因为节点总是应该连接,并等待彼此的请求。但我不能检查程序终止,因为它在import socket import SocketServer import select import sys import threading class Client(SocketServer.ThreadingTCPServer): """Attributes: neighbours: connections to neighbours n_addresses: addresses of Neighbours requests: Number of Requests Sent processed_requests:{} id: this client's id """ def __init__(self, server_address, RequestHandlerClass, id): self.neighbours = [] self.n_addresses = [] self.requests = 0 self.processed_requests = {} self.id = id SocketServer.ThreadingTCPServer.__init__(self, server_address, RequestHandlerClass) def initiateConnection(self, address): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(address) self.neighbours.append(s) self.n_addresses.append(s.getpeername()) self.addConnection(s, address) # check if the given port, and the connected one match if address[1] != s.getpeername()[1]: raise Exception(address, s.getpeername()) """ this method is based on the _handle_request_no_block method on the base server we will add the connection created by this node i.e: this node is the client for that particular connection, to the list of connections handled by this server, i.e: view it as a server connection """ #This method is supposed to add the request first instantiated by # the Client instance itself, to the requests the ThreadingTCPServer manages (creates a seperate thread for it and etc.) # Maybe there's something else I have to do, so that the ThreadingTCPServer closes this connection properly? def addConnection(self, request, address): if self.verify_request(request, address): try: self.process_request(request, address) except: self.handle_error(request, address) self.shutdown_request(request) def addNeighbour(self, s): self.neighbours.append(s) self.n_addresses.append(s.getpeername()) def server_close(self): print("{}: closing neighbours".format(self.id)) for c in self.neighbours: print("{}: closing {}".format(c.getpeername())) c.close() print("{}: closed all neighbours".format(self.id)) SocketServer.ThreadingTCPServer.server_close(self) class RequestHandler(SocketServer.StreamRequestHandler): GET_NEIGHBOURS="1" EOR="EOR" # the below function means someone is trying to initiate # connection, since it will be handled in it's own thread # we will initiate a loop and wait for a request. def handle(self): self.server.addNeighbour(self.request) while True: lines = [] select.select([self.rfile], [], []) print("{}: got request from {}".format(self.server.id, self.request.getpeername())) while True: line = self.rfile.readline().strip() print("line read:\n{}".format(line)) if line == RequestHandler.EOR: break elif not bool(line): continue lines.append(line) print("{}: all request lines read:\n{}".format(self.server.id, lines)) # we have a complete request now process it if lines[1] == self.GET_NEIGHBOURS: print("{}: request was of type get_neighbours".format(self.server.id)) data = self.processNeighbours(lines) self.request.sendall("{}\n".format(data)) print("{}: data sent to {}".format(self.server.id, self.request.getpeername())) class UnknownRequestCode(Exception): pass if __name__ == '__main__': def output(s): print(s) def getLine(): return sys.stdin.readline() address = ('', 0) clients = {} addresses = {} while True: print("commands:\nclose: exit\nnew: make a new client, will prompt for a client id\nshow: show a clients neighbours, will prompt for a client's id\nconnect: will connect a client to another one, will prompt for the ids") i = getLine().strip() if i == "close": for c in clients.values(): c.shutdown() print("everything shut down") sys.exit() if i == "new": i = getLine(). strip() client = Client(address, RequestHandler, i) clients[i] = client a = client.server_address addresses[i] = a output(a) t = threading.Thread(target=client.serve_forever) t.daemon = True t.start() elif i == "show": i = getLine().strip() c = clients[i] o = c.startSearch() #output(o) elif i == "connect": i = getLine().strip() c = clients[i] i = getLine().strip() a = addresses[i] print("{}".format(a)) c.initiateConnection(a) 调用之前卡住了。我该如何解决?

2 个答案:

答案 0 :(得分:0)

当所有线程退出时,python程序结束。我认为你的线程函数没有返回,这意味着即使你调用exit(),程序也会等待它们返回。

如果是这种情况(我真的认为是这样),那么一个简单的解决方案就是拥有一个全局'running'标志= True:

running = True

并在每个线程内部创建一个循环,在运行之前检查此标志:

#thread function
def thread_function ():
    #loop checks the flag
    while running:
        pass    #write loop code here
    #if running turns to false, then you will be here
    pass    #write clean up code here

希望有所帮助

答案 1 :(得分:0)

由于RequestHandler.handle在无限循环中运行,并等待来自另一方的请求,反之亦然,我们必须在主进程退出时终止它。密钥在SocketServer.ThreadingMixin.daemon_threads必须是设置为true,以便最终运行handle方法的创建线程将在退出时终止。