Python - 如何正确设置函数的超时

时间:2016-11-18 22:23:48

标签: python

我有两个名为on_outbounddata()on_execute的函数我希望这些函数的超时时间为3秒,如果超过3秒则退出函数并继续运行其他函数。这是我的代码:

import socket,select,time,base64,os,sys,re,datetime, signal

class TheServer:
    input_list = []
    channel = {}
    channel_ = {}
    request = {}

    def handler(self, signum, frame):
        print "Time is up (3 sec)"
        raise Exception("end of time")

    def main_loop(self):
        self.input_list.append(self.server)
        while 1:
            ss = select.select
            inputready, outputready, exceptready = ss(self.input_list, [], [])
            for self.s in inputready:
                if self.s == self.server:
                    self.on_accept()
                    break
                try:
                    self.netdata = self.s.recv(buffer_size)
                except Exception, e:
                    self.netdata =''
                if len(self.netdata) == 0:
                    self.on_close()
                else:
                    signal.signal(signal.SIGALRM, self.handler)
                    signal.alarm(3)
                    try:
                        if cmp(self.channel[self.s],self.channel_[self.s]):
                            self.on_outbounddata() # I want this function to have a timeout of 3 seconds
                        else:
                            self.on_execute() # I want this function to have a timeout of 3 seconds
                    except Exception, exc: 
                        print exc

        def on_execute(self):
            print "ON_EXECUTE"
            netdata = self.netdata
    #-----------------------------------------------------------
            if netdata.find("CONNECT") ==0:
                req="CONNECT " + host + ":" + port
                payloads=payload           
                payloads=payloads.replace('^request^',req)
                ms = re.search(r"\^s(\d+)\^", payloads)
                if ms:
                  pay=payloads.split('^s'+ms.group(1)+'^')
                  self.request[self.channel[self.s]]=pay[1];
                  netdata=pay[0]
                else:
                     netdata=payloads
                #print netdata
            try:
                self.channel[self.s].send(netdata)
            except Exception, e:
                print e            
    #-----------------------------------------------------------
        def on_outbounddata(self):
            print "ON_OUTBOUNDDATA"
            netdata = self.netdata
            if netdata.find('HTTP/1.') ==0:
                ms = re.search(r"\^s(\d+)\^", payload)
                if ms:
                  print "Sleeping for " + ms.group(1) + "ms"
                  dec = int(ms.group(1)) / float(1000)
                  time.sleep(dec)
                  print self.request[self.s]
                  try:
                    self.channel_[self.s].send(self.request[self.s])
                    self.request[self.s]=''
                  except ValueError:
                    print "self.s is not in the list (on_outbounddata)"
                    pass
                netdata='HTTP/1.1 200 Connection established\r\n\r\n'
            try:
                self.channel[self.s].send(netdata)
            except Exception, e:
                print e
            except:
                pass

请注意,我只想将暂停时间应用于on_outbounddata()on_execute。当我运行该代码时,它不会继续运行其他函数,而只是打破while循环。我该如何解决这个问题?

这是错误输出:

ON_EXECUTE
ON_EXECUTE
ON_OUTBOUNDDATA
ON_OUTBOUNDDATA
ON_CLOSE
ON_CLOSE
Time is up (3 sec)
Traceback (most recent call last):
  File "/usr/bin/socks", line 278, in <module>
    server.main_loop()
  File "/usr/bin/socks", line 159, in main_loop
    inputready, outputready, exceptready = ss(self.input_list, [], [])
  File "/usr/bin/socks", line 152, in handler
    raise Exception("end of time")
Exception: end of time

1 个答案:

答案 0 :(得分:1)

您的问题是因为您之后没有取消设置警报,所以它会继续,3秒后它会触发,即使您不再处于想要超时的部分。 The documentation解释了如何执行此操作:

  

signal.alarm(time)如果时间不为零,则此函数请求a   SIGALRM信号在时间秒内发送到进程。任何先前的   预定警报被取消(任何警报只能安排一个警报   时间)。返回值则是之前的秒数   以前设定的警报已经发出。 如果时间为零,则不   警报已安排,任何预定警报已取消。如果退货   值为零,当前没有安排警报。 (参见Unix手册页   alarm(2)。)可用性:Unix。