【python2】commands模塊getstatusoutput函數的小問題
阿新 • • 發佈:2019-03-03
new con modified ipp let pro man http this [TOC]
問題
import commands as subprocess
status, _ = subprocess.getstatusoutput("ps -elf|grep fuckU")
# status:
# 255
-
這裏的status按照grep的定義其實應該返回1,也就是沒有grep到匹配項,在shell中echo $? 結果為1
但是python2
的getstatusoutput
獲取的並不是os.exitcode()
而是os.wait()
的返回值。 python3
由於使用的是subprocess = modified(commands + subprocess)
,同樣執行status, _ = subprocess.getstatusoutput("ps -elf|grep fuckU")
得到的status為正確的1
我是怎麽解決這個問題
兼顧Python2和Python3的使用習慣,使用google開源的subprocess32代替commands
什麽是subprocess32
谷歌將Python32的subprocess移植到了python2版本中。據說這是線程安全的版本。
最新的Python32版本為3.5.3也就是將python3.5.3中的subprocess基本功能移植到了Python2中。但是subprocess32不包含原本commands中的函數。
Timeout support backported from Python 3.3 is included. The run() API from Python 3.5 was backported in subprocess32 3.5.0. Otherwise features are frozen at the 3.2 level.
這裏我們使用subprocess32.run()方法去模擬getstatusoutput等便捷的函數(python3官方實現)
# 原本的timeout=None,因為Python2不支持*args,**kwargs外再有kwargs,暫時移出參數項,放至函數體內 # def check_output(*popenargs, timeout=None, **kwargs): def check_output(*popenargs, **kwargs): r"""Run command with arguments and return its output. If the exit code was non-zero it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute and output in the output attribute. The arguments are the same as for the Popen constructor. Example: >>> check_output(["ls", "-l", "/dev/null"]) b‘crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n‘ The stdout argument is not allowed as it is used internally. To capture standard error in the result, use stderr=STDOUT. >>> check_output(["/bin/sh", "-c", ... "ls -l non_existent_file ; exit 0"], ... stderr=STDOUT) b‘ls: non_existent_file: No such file or directory\n‘ There is an additional optional argument, "input", allowing you to pass 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 too will be used internally. Example: >>> check_output(["sed", "-e", "s/foo/bar/"], ... input=b"when in the course of fooman events\n") b‘when in the course of barman events\n‘ If universal_newlines=True is passed, the "input" argument must be a string and the return value will be a string rather than bytes. """ timeout = None if ‘stdout‘ in kwargs: raise ValueError(‘stdout argument not allowed, it will be overridden.‘) if ‘input‘ in kwargs and kwargs[‘input‘] is None: # Explicitly passing input=None was previously equivalent to passing an # empty string. That is maintained here for backwards compatibility. kwargs[‘input‘] = ‘‘ if kwargs.get(‘universal_newlines‘, False) else b‘‘ return subprocess.run(*popenargs, stdout=subprocess.PIPE, timeout=timeout, check=True, **kwargs).stdout def getstatusoutput(cmd): """Return (exitcode, output) of executing cmd in a shell. Execute the string ‘cmd‘ in a shell with ‘check_output‘ and return a 2-tuple (status, output). The locale encoding is used to decode the output and process newlines. A trailing newline is stripped from the output. The exit status for the command can be interpreted according to the rules for the function ‘wait‘. Example: >>> import subprocess >>> subprocess.getstatusoutput(‘ls /bin/ls‘) (0, ‘/bin/ls‘) >>> subprocess.getstatusoutput(‘cat /bin/junk‘) (1, ‘cat: /bin/junk: No such file or directory‘) >>> subprocess.getstatusoutput(‘/bin/junk‘) (127, ‘sh: /bin/junk: not found‘) >>> subprocess.getstatusoutput(‘/bin/kill $$‘) (-15, ‘‘) """ try: data = check_output(cmd, shell=True, universal_newlines=True, stderr=subprocess.STDOUT) exitcode = 0 except subprocess.CalledProcessError as ex: data = ex.output exitcode = ex.returncode if data[-1:] == ‘\n‘: data = data[:-1] return exitcode, data def getoutput(cmd): """Return output (stdout or stderr) of executing cmd in a shell. Like getstatusoutput(), except the exit status is ignored and the return value is a string containing the command‘s output. Example: >>> import subprocess >>> subprocess.getoutput(‘ls /bin/ls‘) ‘/bin/ls‘ """ return getstatusoutput(cmd)[1]
題外話
其實python官方推薦使用這個函數執行系統命令subprocess.run()
但是這個函數將輸出直接print到終端中
如果需要屏蔽恣意的屏幕輸出,可以使用subprocess.DEVNULL
(subprocess 3.5.3中有)
# 即
x = subprocess.run(‘echo 250‘, shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
# x:
# CompletedProcess(args=‘echo 250‘, returncode=0)
# reference: https://stackoverflow.com/questions/8529390/is-there-a-quiet-version-of-subprocess-call
【python2】commands模塊getstatusoutput函數的小問題