接受的答案是无效代码,也没有与原始 (Python 3) 函数相同的返回值。然而,它足够相似,它不是 CC BY 4.0 Martijn Pieters,因为它是从 Python 复制的,并且如果任何许可适用于琐碎代码(我完全反对琐碎代码的许可,因为它阻碍了创新并证明所有权或独创性很难,因此 stackoverflow 可能会违反包括 GPL 在内的各种许可证,方法是通过重新许可人们粘贴并默认声明为自己的东西而不引用来源来增加额外的限制),这将在下面的 GitHub 链接中。如果代码不能以相同的方式使用,则不是“反向移植”。如果您尝试以 Python 3 方式使用它而不更改代码(使用该函数的客户端代码),您将只有“AttributeError:'tuple' 对象没有属性 'returncode'”。您可以更改您的代码,但它不会与 Python 3 兼容。
无论哪种方式,接受的答案本身的代码都不会运行,原因是:
-
“TypeError: init() got an unexpected keyword argument 'stderr'”(因为 stderr 在 2 或 3 中都不是“CalledProcessError”的参数)
-
“AttributeError: 'Popen' object has no attribute 'args'”(args 仅在 Python 3 中可用)
因此,请考虑更改接受的答案。
为了更加 Pythonic,利用鸭子类型和猴子补丁(您的客户端代码可以保持不变,并为 run 方法和返回的对象的类使用下面显示的不同定义),这里是一个兼容的实现Python 3:
import subprocess
try:
from subprocess import CompletedProcess
except ImportError:
# Python 2
class CompletedProcess:
def __init__(self, args, returncode, stdout=None, stderr=None):
self.args = args
self.returncode = returncode
self.stdout = stdout
self.stderr = stderr
def check_returncode(self):
if self.returncode != 0:
err = subprocess.CalledProcessError(self.returncode, self.args, output=self.stdout)
raise err
return self.returncode
def sp_run(*popenargs, **kwargs):
input = kwargs.pop("input", None)
check = kwargs.pop("handle", False)
if input is not None:
if 'stdin' in kwargs:
raise ValueError('stdin and input arguments may not both be used.')
kwargs['stdin'] = subprocess.PIPE
process = subprocess.Popen(*popenargs, **kwargs)
try:
outs, errs = process.communicate(input)
except:
process.kill()
process.wait()
raise
returncode = process.poll()
if check and returncode:
raise subprocess.CalledProcessError(returncode, popenargs, output=outs)
return CompletedProcess(popenargs, returncode, stdout=outs, stderr=errs)
subprocess.run = sp_run
# ^ This monkey patch allows it work on Python 2 or 3 the same way
此代码已使用我的 install_any.py 中适用于 Python 2 和 3 的测试用例进行了测试(请参阅 https://github.com/poikilos/linux-preinstall/tree/master/utilities)。
注意:该类没有相同的 repr 字符串,并且可能有其他细微差别(您可以根据其许可证在以下 URL 使用 Python 3 本身的真实代码 - 请参阅class CalledProcess in:https://github.com/python/cpython/blob/master/Lib/subprocess.py -- 如果有的话,该许可证也适用于我的代码,但我将它作为 CC0 发布,因为我认为它是微不足道的 -- 请参阅上面括号中的解释。
#IRejectTheInvalidAutomaticLicenseForMyPost