subprocess
运行一个进程
subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用。 1. subprocess.call() 函数格式如下: call(*popenargs,timeout=None,**kwargs): """Run command with arguments. Wait for command to complete or timeout,then return the returncode attribute. The arguments are the same as for the Popen constructor. Example: retcode = call(["ls","-l"]) 父进程等待子进程完成 >>> import subprocess >>> retcode = subprocess.call(["ls","-l"]) #和shell中命令ls -a显示结果一样 >>> print retcode 0 或者是 >>> a = subprocess.call(['df','-hT'],shell=False) Filesystem Type Size Used Avail Use% Mounted on /dev/sda2 ext4 94G 64G 26G 72% / tmpfs tmpfs 2.8G 0 2.8G 0% /dev/shm /dev/sda1 ext4 976M 56M 853M 7% /boot subprocess.check_call():用法与subprocess.call()类似,区别是,当返回值不为0时,直接抛出异常 >>> a = subprocess.check_call('df -hT',shell=True) Filesystem Type Size Used Avail Use% Mounted on /dev/sda2 ext4 94G 64G 26G 72% / tmpfs tmpfs 2.8G 0 2.8G 0% /dev/shm /dev/sda1 ext4 976M 56M 853M 7% /boot >>> print a 0 >>> a = subprocess.check_call('dfdsf',shell=True) /bin/sh: dfdsf: command not found Traceback (most recent call last): File "<stdin>",line 1,in <module> File "/usr/lib64/python2.6/subprocess.py",line 502,in check_call raise CalledProcessError(retcode,cmd) subprocess.CalledProcessError: Command 'dfdsf' returned non-zero exit status 127 2. subprocess.Popen()
函数形式如下: class Popen(args,bufsize=0,executable=None,stdin=None,stdout=None,stderr=None,preexec_fn=None,close_fds=False,shell=False,cwd=None,env=None,universal_newlines=False,startupinfo=None,creationflags=0) Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block) import subprocess if __name__ == "__main__": child = subprocess.Popen('ping -c www.baidu.com',shell=True) child.wait() print('parent process') ? 父进程在开启子进程之后并等待child的完成后,再运行print。 child.poll() # 检查子进程状态 子进程的标准输入、标准输出和标准错误, 如下属性分别表示: 示例,将一个子进程的输出,作为另一个子进程的输入: import subprocess child1 = subprocess.Popen(["cat","/etc/passwd"],stdout=subprocess.PIPE) child2 = subprocess.Popen(["grep","0:0"],stdin=child1.stdout,stdout=subprocess.PIPE) out = child2.communicate() 案例分析: 在工作中经常会遇到这样的需求: 需要采用python来运行一个shell脚本,如何优雅的操作呢? 解决方案: ? 用python的subprocess去执行传递过来的脚本,通常情况下subprocess都能运行的很好,完成脚本的执行并返回。 可以采用如下代码实现: # -*- coding: utf-8 -*- __author__ = 'sun' __date__ = '2019/5/28 18:26' import subprocess from threading import Timer import os import time import signal class TestSubProcess(object): def __init__(self): self.stdout = [] self.stderr = [] self.timeout = 6 self.is_timeout = False def timeout_callback(self,p): print('exe time out call back') try: p.kill() # os.killpg(p.pid,signal.SIGKILL) except Exception as error: print(error) def run(self): stdout = open('/tmp/subprocess_stdout','wb') stderr = open('/tmp/subprocess_stderr','wb') cmd = ['bash','/home/xxx/while_test.sh'] ps = subprocess.Popen(cmd,stdout=stdout.fileno(),stderr=stderr.fileno()) my_timer = Timer(self.timeout,self.timeout_callback,[ps]) my_timer.start() print(ps.pid) try: print("start to count timeout; timeout set to be %d n" % (self.timeout,)) ps.wait() finally: my_timer.cancel() stdout.flush() stderr.flush() stdout.close() stderr.close() if __name__ == "__main__": tsp = TestSubProcess() tsp.run() 总结: ? 关于p = subprocess.Popen,最好用p.communicate.而不是直接用p.wait(), 因为p.wait()有可能因为子进程往PIPE写的时候写满了,但是子进程还没有结束,导致子进程阻塞,而父进程一直在wait(),导致父进程阻塞。而且p.wait()和p.communicate不能一起用,因为p.communicate里面也会去调用wait()。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |