subprocess.check_output()似乎不存在(Python 2.6.5)
我在看Python的文档,特别是关于subprocess模块的部分(可以在这里找到)。文档里提到有个subprocess.check_output()
命令,听起来正是我需要的。
可是,当我尝试使用这个命令时,出现了一个错误,提示这个命令不存在。而且当我运行dir(subprocess)
时,它也没有在列表中。
我现在使用的是Python 2.6.5,下面是我用的代码:
import subprocess
subprocess.check_output(["ls", "-l", "/dev/null"])
有没有人知道为什么会这样呢?
3 个回答
6
感谢猴子补丁的建议(虽然我尝试了几次都失败了 - 但我们需要处理CalledProcessError的输出,所以需要用猴子补丁来解决这个问题)
我在这里找到了一个可以用的2.6版本的补丁:http://pydoc.net/Python/pep8radius/0.9.0/pep8radius.shell/
"""Note: We also monkey-patch subprocess for python 2.6 to
give feature parity with later versions.
"""
try:
from subprocess import STDOUT, check_output, CalledProcessError
except ImportError: # pragma: no cover
# python 2.6 doesn't include check_output
# monkey patch it in!
import subprocess
STDOUT = subprocess.STDOUT
def check_output(*popenargs, **kwargs):
if 'stdout' in kwargs: # pragma: no cover
raise ValueError('stdout argument not allowed, '
'it will be overridden.')
process = subprocess.Popen(stdout=subprocess.PIPE,
*popenargs, **kwargs)
output, _ = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise subprocess.CalledProcessError(retcode, cmd,
output=output)
return output
subprocess.check_output = check_output
# overwrite CalledProcessError due to `output`
# keyword not being available (in 2.6)
class CalledProcessError(Exception):
def __init__(self, returncode, cmd, output=None):
self.returncode = returncode
self.cmd = cmd
self.output = output
def __str__(self):
return "Command '%s' returned non-zero exit status %d" % (
self.cmd, self.returncode)
subprocess.CalledProcessError = CalledProcessError
58
如果你要运行的代码中大量使用了某个功能,但这些代码不需要长期维护(或者你需要一个快速解决方案,不管将来可能带来的维护麻烦),那么你可以在导入subprocess的地方进行“鸭子打补丁”(也叫“猴子补丁”)...
只需从2.7版本中提取相关代码,然后这样插入...
import subprocess
if "check_output" not in dir( subprocess ): # duck punch it in!
def f(*popenargs, **kwargs):
if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.')
process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise subprocess.CalledProcessError(retcode, cmd)
return output
subprocess.check_output = f
可能需要进行一些小调整。
不过要记住,维护这些“脏补丁”的责任在你。如果在最新的Python版本中发现并修复了错误,你就得 a) 注意到这一点,b) 如果想保持安全,就得更新你的版本。此外,自己重写和定义内部函数会让后续的开发者非常头疼,尤其是当几年后你自己再来维护时,你可能会忘记之前做的那些“黑科技”了!总的来说:这通常不是个好主意。
123
这个功能是在2.7版本中引入的,详细信息可以查看文档。
如果你想获取输出,可以使用subprocess.Popen:
>>> import subprocess
>>> output = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE).communicate()[0]