def run(*popenargs, input=None, capture_output=False, timeout=None, check=False, **kwargs): """Run command with arguments and return a CompletedProcess instance. The returned instance will have attributes args, returncode, stdout and stderr. By default, stdout and stderr are not captured, and those attributes will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them. If check is True and the exit code was non-zero, it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute, and output & stderr attributes if those streams were captured. If timeout is given, and the process takes too long, a TimeoutExpired exception will be raised. There is an optional argument "input", allowing you to pass bytes or a string to the subprocess's stdin. If you use this argument you may not also use the Popen constructor's "stdin" argument, as it will be used internally. By default, all communication is in bytes, and therefore any "input" should be bytes, and the stdout and stderr will be bytes. If in text mode, any "input" should be a string, and stdout and stderr will be strings decoded according to locale encoding, or by "encoding" if set. Text mode is triggered by setting any of text, encoding, errors or universal_newlines. The other arguments are the same as for the Popen constructor. """ if input is not None: if 'stdin' in kwargs: raise ValueError('stdin and input arguments may not both be used.') kwargs['stdin'] = PIPE if capture_output: if ('stdout' in kwargs) or ('stderr' in kwargs): raise ValueError('stdout and stderr arguments may not be used ' 'with capture_output.') kwargs['stdout'] = PIPE kwargs['stderr'] = PIPE with Popen(*popenargs, **kwargs) as process: try: stdout, stderr = process.communicate(input, timeout=timeout) except TimeoutExpired: process.kill() stdout, stderr = process.communicate() raise TimeoutExpired(process.args, timeout, output=stdout, stderr=stderr) except: # Including KeyboardInterrupt, communicate handled that. process.kill() # We don't call process.wait() as .__exit__ does that for us. raise retcode = process.poll() if check and retcode: raise CalledProcessError(retcode, process.args, output=stdout, stderr=stderr) return CompletedProcess(process.args, retcode, stdout, stderr)
可以看到返回的是一個completeProcess對象
class CompletedProcess(object): """A process that has finished running. This is returned by run(). Attributes: args: The list or str args passed to run(). returncode: The exit code of the process, negative for signals. stdout: The standard output (None if not captured). stderr: The standard error (None if not captured). """ def __init__(self, args, returncode, stdout=None, stderr=None): self.args = args self.returncode = returncode self.stdout = stdout self.stderr = stderr def __repr__(self): args = ['args={!r}'.format(self.args), 'returncode={!r}'.format(self.returncode)] if self.stdout is not None: args.append('stdout={!r}'.format(self.stdout)) if self.stderr is not None: args.append('stderr={!r}'.format(self.stderr)) return "{}({})".format(type(self).__name__, ', '.join(args)) def check_returncode(self): """Raise CalledProcessError if the exit code is non-zero.""" if self.returncode: raise CalledProcessError(self.returncode, self.args, self.stdout, self.stderr)
所以調用獲取最終returncode可以使用
sub=subproccess.run(xxxxx)
returncode,out,err,args=sub.returncode,sub.stdout,sub.stderr,sub.args
#!/usr/bin/python3 # coding=gbk import os import sys curPath = os.path.abspath(os.path.dirname(__file__)) rootPath = os.path.split(curPath)[0] sys.path.append(rootPath) import subprocess import platform from src import logutils log=logutils.logger("app",rootstdout=True,handlerList=['I','E']) """
if check=True then returncode ==0 return stdout normal,
returncode!=0 rasise callProcessError ,check=False nothing to do
""" def subprocess_run(): str_shell='df -m &&netstat -ntslp|grep 11111' CompletedProcessObject=subprocess.run(args=str_shell,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True,timeout=10,check=False) if CompletedProcessObject: code,out,err=CompletedProcessObject.returncode,CompletedProcessObject.stdout,CompletedProcessObject.stderr if code ==0: if out: #log.info("執行isok!!!!") log.info(out) return out if err: log.error(err) return err else: if code ==1: log.error("語法輸出對象為空") else: #log.info(code) raise subprocess.CalledProcessError(code,str_shell) def run(): str_shell='df -m && netstat -ntlp' sub=subprocess.Popen(args=str_shell,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True) out,err=sub.communicate() #res=sub.stdout.readlines() if sub.returncode == 0: #log.info("returncode is 0,執行輸出正常") if out: log.info("執行輸出正常") log.info(out) if err: log.error("出現異常") log.error(err,exc_info=True) else: if sub.returncode == 1: log.error("執行shell對象結果有空") else: raise subprocess.CalledProcessError(sub.returncode, str_shell) def operate_sys(): plat_tuple=platform.architecture() system=platform.system() plat_version=platform.platform() if system == 'Windows': return system,plat_version # log.info('this is windows system') # log.info('version is: '+plat_version) elif system == 'Linux': return system,plat_version # log.info('this is linux system ') # log.info('version is: '+plat_version) if __name__ == '__main__': subprocess_run()
正常check=True時 returncode=0代表結果都輸出正常
[root@hostuser src]# python3 subprocess_popen.py
[INFO]2019-05-19 21:01:59 Sun --app-- subprocess_popen.py:
執行isok!!!!
[INFO]2019-05-19 21:01:59 Sun --app-- subprocess_popen.py:
Filesystem 1M-blocks Used Available Use% Mounted on
/dev/mapper/centos-root 27627 8652 18975 32% /
devtmpfs 894 0 894 0% /dev
tmpfs 910 1 910 1% /dev/shm
tmpfs 910 11 900 2% /run
tmpfs 910 0 910 0% /sys/fs/cgroup
/dev/sda1 1014 232 783 23% /boot
tmpfs 182 1 182 1% /run/user/42
tmpfs 182 0 182 0% /run/user/0
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.81.129 netmask 255.255.255.0 broadcast 192.168.81.255
inet6 fe80::f08c:a9:42b2:6ec4 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:11:d6:35 txqueuelen 1000 (Ethernet)
RX packets 16609 bytes 1344727 (1.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 9525 bytes 1168830 (1.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 194415 bytes 161261315 (153.7 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 194415 bytes 161261315 (153.7 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
ether 52:54:00:4a:9f:2c txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
正常check=True時拋出異常1代表執行結果有空:
[root@hostuser src]# python3 subprocess_popen.py
Traceback (most recent call last):
File "subprocess_popen.py", line 73, in <module>
subprocess_run()
File "subprocess_popen.py", line 17, in subprocess_run
stderr=subprocess.PIPE,universal_newlines=True,timeout=10,check=True)
File "/usr/local/lib/python3.7/subprocess.py", line 487, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'df -m &&netstat -ntslp|grep 11111' returned non-zero exit status 1.
check=False:異常時則如果你不做處理返回空
正常還是返回stdout結果