sys.exit()未在python中退出 [英] sys.exit() not exiting in python

查看:121
本文介绍了sys.exit()未在python中退出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用socketSocketServer的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆