美文网首页
Subprocess管道卡死问题

Subprocess管道卡死问题

作者: _艾_斯_ | 来源:发表于2020-03-20 11:08 被阅读0次

    <center><font face="黑体" bgcolor=#7FFFD4 size=5>Subprocess管道卡死</font></center>

    • 进程实现方法
    import subprocess                                                                
    import threading                                                                 
    import time                                                                      
                                                                                        
                                                                                        
    class TimeoutError(Exception):                                                      
        pass                                                                            
                                                                                        
    class SubProcess(threading.Thread):                                                 
                                                                                        
        def __init__(self, cmd, timeout=None):                                       
                                                                                        
            super(SubProcess,self).__init__()                                           
                                                                                        
            self.cmd = cmd                                                              
            self.event = threading.Event()                                              
            self.stdout = ""                                                            
            self.stderr = ""                                                            
            self.retcode = None                                                         
            self.timeout = timeout                                                      
                                                                                        
                                                                                        
        def run(self):                                                                  
            try:                                                                        
                start_time = time.time()                                                
                read_flag = end_flag = False                                            
                PIPE = subprocess.PIPE                                                  
                sub = subprocess.Popen(self.cmd, shell=True, stderr=PIPE, stdout=PIPE)
                                                                                        
                while not self.event.is_set():                                          
                                                                                        
                    end_time = time.time()                                              
                    if self.timeout and (end_time-start()) >= self.timeout: 
                        self.retcode = -1                                            
                        self.stderr = "TimeOut"                                      
                        sub.terminate()                                              
                        break                                                        
                    if not self.retcode == None and read_flag:                       
                        break                                                        
                                                                                     
                    if not read_flag:                                                
                        line = sub.stdout.readline()                                 
                        if line:                                                     
                            self.stdout += line                                      
                        else:                                                        
                            read_flag = True                                         
                                                                                     
                    if self.retcode ==  None:                                        
                        self.retcode = sub.poll()                                    
                                                                                     
            except Exception, ex:                                                    
                self.retcode = -1                                                    
                self.stderr = ex                                                     
                                                                                     
        def stop(self):                                                              
            self.event.set()                                                         
                                                                                     
    sub = SubProcess("ls -l /root/")                                                 
                                                                                     
    sub.start()                                                                      
    sub.join()                                                                       
    print repr(sub.stdout)                                                           
    #print sub.stderr                                                                
    print sub.retcode
    
    • 函数实现方法
    def exec_command_ex(cmd, timeout=0):                                             
        stdout = stderr = ""                                                         
        start = time.time()                                                          
        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,                
                             close_fds=True, stderr=subprocess.PIPE)                 
        while p.poll() is None:                                                      
            now = time.time()                                                        
            if timeout > 0 and (now - start) > timeout:                                 
                try:                                                                    
                    p.terminate()                                                       
                except Exception as e:                                                  
                    return -1, None, None                                               
                                                                                        
            stdout += sub.stdout.read()                                                 
            stderr += sub.stderr.read()                                                 
            time.sleep(0.1)                                                             
        if p:                                                                           
            ret = p.returncode                                                          
            if p.stdin:                                                                 
                p.stdin.close()                                                         
            if p.stdout:                                                                
                p.stdout.close()                                                        
            if p.stderr:                                                                
                p.stderr.close()                                                        
            try:                                                                     
                p.kill()                                                                
            except OSError:                                                             
                pass                                                                    
            return ret, stdout, stderr                                                  
        else:                                                                           
            return -1, None, None
    
    • 终极实现方式

      import subprocess
      import threading
      import time
      
      
      class TimeoutError(Exception):
          pass
      
      class SubProcess(threading.Thread):
      
          def __init__(self, cmd, timeout=None):
      
              super(SubProcess,self).__init__()
      
              self.cmd = cmd
              self.event = threading.Event()
              self.stdout = ""
              self.stderr = ""
              self.retcode = None
              self.timeout = timeout
      
      
          def run(self):
              try:
                  start_time = time.time()
                  read_flag = end_flag = False
                  PIPE = subprocess.PIPE
                  sub = subprocess.Popen(self.cmd, shell=True, stderr=PIPE, stdout=PIPE)
      
                  while not self.event.is_set() and sub.poll() is None:
      
                     self.stdout += sub.stdout.read()
      
                     time.sleep(0.05)
      
                  self.stderr +=sub.stderr.read()
                  self.retcode = sub.returncode
                  
                          except Exception, ex:
                  self.retcode = -1
                  self.stderr = ex
      
          def stop(self):
              self.event.set()
      
      def exec_command_ex(cmd, timeout=30):
          myout = ""
          myerror = ""
      
          start_time = end_time = time.time()
          #import pdb;pdb.set_trace()
          sub = SubProcess(cmd,5)
          sub.start()
      
          while True:
      
              if (end_time - start_time) > timeout:
                  sub.stop()
                  sub._Thread__stop()
                  sub.retcode = 124
                  sub.stderr = TimeoutError
                  break
      
              if not sub.is_alive():
                  break
      
              time.sleep(0.1)
              end_time = time.time()
      
          return sub.retcode,sub.stdout,sub.stderr
      
      #cmd = "cat /var/log/message"
      cmd = "sleep 10000"
      #cmd = "ls| grep 111"
      retcode,stdout,stderr =  exec_command_ex(cmd,5)
      print retcode,stderr
      

    相关文章

      网友评论

          本文标题:Subprocess管道卡死问题

          本文链接:https://www.haomeiwen.com/subject/zoodyhtx.html