sys.exit()未在python中退出 [英] sys.exit() not exiting in python
问题描述
我有一个使用socket
和SocketServer
的python2程序.它基本上由一些可以相互连接的客户端组成.每个客户端也有自己的Thread
,该Thread
使用threading.Thread
实现并以daemon
模式运行.现在我的问题是当我调用sys.exit()
时程序没有退出.我也(试图)在sys.exit()
调用之前关闭所有打开的套接字.我也在程序中使用了socket.makefile()
,但是我调用了close
我在读取所有打开的文件后立即对它们进行处理.如果sys.exit()
不退出,可能是什么原因?
I have a python2 program which uses socket
and SocketServer
. it basically consists of some clients, that can connect with each other.Each Client also has their own Thread
which is implemented using threading.Thread
and run in daemon
mode. Now my problem is that when i call sys.exit()
the program doesn't exit.I also (try to) close all open sockets before sys.exit()
call.I also use socket.makefile()
in the program, however I call close
on all of the opened files right after I read from them.What could be the potential causes if sys.exit()
not exiting?
这是代码,应用程序应该代表节点图,
如果我们在第一个节点上调用initiateConnection
并用第二个节点的地址调用每个节点,则每个节点都将包含一个Edge到另一个节点.由于Edge是无方向的,我希望套接字的两侧都由相同的RequestHandler
处理. Client.initiateConnection
上的注释.
Here's the code, the application is supposed to represent a graph of nodes,
each node will contain an Edge to another node if we call initiateConnection
on the first node with the address of the second one.Since the Edges are undirected I want both sides of the socket to be handled by the same RequestHandler
.See notes above Client.initiateConnection
.
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)
更新:我已经发现了(很明显)的问题,由于总是应该将节点连接起来并等待对方的请求,因此handle方法永远不会退出循环.但是我不能检查程序终止,因为它在select.select
调用之前卡住了.我该如何解决?
UPDATE: I have identified the (rather obvious) problem, the handle method never exits the loop since the nodes are always supposed to get connected, and wait for each other's request.But I can not check program termination since it gets stuck before the select.select
call.How can I fix that?
推荐答案
由于RequestHandler.handle
在无限循环中运行,并且等待另一端的请求,反之亦然,因此我们必须在主进程退出时终止它.密钥位于SocketServer.ThreadingMixin.daemon_threads
中,必须将其设置为true,以便最终将运行handle方法的已创建线程将在退出时终止.
Since the RequestHandler.handle
runs in an infinite loop, and waits for request from the other side and vice versa, we must terminate it when the main process exits.The key was in SocketServer.ThreadingMixin.daemon_threads
which must be set to true, so that the created threads that will eventually run the handle method will be terminated upon exit.
这篇关于sys.exit()未在python中退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!