Subprocess管道卡死问题

<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
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 必备的理论基础 1.操作系统作用: 隐藏丑陋复杂的硬件接口,提供良好的抽象接口。 管理调度进程,并将多个进程对硬件...
    drfung阅读 8,931评论 0 5
  • 顾名思义,进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。进程的概念起源于操作系统,是操作系统最核心的概...
    SlashBoyMr_wang阅读 4,876评论 0 3
  • 最近在项目中遇到一个需求,前端发来一个命令,这个命令是去执行传递过来的一个脚本(shell 或者python),并...
    llicety阅读 50,173评论 8 19
  • ###总结得很不错!!### Python标准库06 子进程 (subprocess包) 作者:Vamei 出处:...
    Shirley_奋进中的虾米阅读 4,900评论 0 5
  • 什么是进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单...
    可笑的黑耀斑阅读 4,626评论 0 0