2016-11-18 96 views
2

我有兩個函數叫做on_outbounddata()on_execute我希望這些函數的超時時間爲3秒,如果它們花費的時間超過3秒,則退出函數並繼續運行其他函數。這裏是我的代碼:Python - 如何正確設置函數的超時時間

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

首先,請永遠不要這樣做['除外:pass'(http://stackoverflow.com/questions/21553327/why-is-except-pass-a-bad -programming實踐)。這會壓制一切,默默地,這意味着你不知道發生了什麼。刪除它並嘗試它,你可能會驚訝什麼是真正殺死你的程序。 – TemporalWolf

+0

好的,但我們能不能專注於暫停而不是那個?我已經更新了錯誤輸出的帖子,請再次看看@TemporalWolf – hillz

+0

這與調試直接相關 - 如果看不到錯誤,則無法向我顯示它以及誰知道發生了什麼。在我能回答你的問題之前,我需要錯誤信息,'except:pass'可以取消錯誤信息。 – TemporalWolf

回答

1

你的問題是因爲你沒有取消設置報警之後,所以它繼續和3秒後它會觸發,即使你在一節已不再你想超時。 The documentation解釋如何做到這一點:

signal.alarm(time) If time is non-zero, this function requests that a SIGALRM signal be sent to the process in time seconds. Any previously scheduled alarm is canceled (only one alarm can be scheduled at any time). The returned value is then the number of seconds before any previously set alarm was to have been delivered. If time is zero, no alarm is scheduled, and any scheduled alarm is canceled. If the return value is zero, no alarm is currently scheduled. (See the Unix man page alarm(2).) Availability: Unix.

+0

謝謝,在函數似乎解決了問題後添加'signal.alarm(0)'。 – hillz