Getting an error - AttributeError: 'module' object has no attribute 'run' while running subprocess.run(["ls", "-l"])

Getting an error - AttributeError: 'module' object has no attribute 'run' while running subprocess.run(["ls", "-l"])

我 运行 在 AIX 6.1 上使用 Python 2.7。想执行以下行但出现错误。

subprocess.run(["ls", "-l"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'run'

subprocess.run() function 仅存在于 Python 3.5 和更新版本中。

然而向后移植很容易:

def 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:
        stdout, stderr = process.communicate(input)
    except:
        process.kill()
        process.wait()
        raise
    retcode = process.poll()
    if check and retcode:
        raise subprocess.CalledProcessError(
            retcode, process.args, output=stdout, stderr=stderr)
    return retcode, stdout, stderr

不支持超时,也没有自定义 class 已完成的进程信息,所以我只返回 retcodestdoutstderr 信息.否则它和原来的一样。

已接受的答案是无效代码,并且 returns 与原始 (Python 3) 函数不同。然而,它非常相似,它不是 CC BY 4.0 Martijn Pieters,因为它是从 Python 复制的,并且如果任何许可适用于琐碎的代码(我完全反对琐碎代码的许可,因为它阻碍了创新和证明所有权或原创性是困难的,因此 Whosebug 可能会违反包括 GPL 在内的各种许可,通过重新许可人们粘贴并默示声明为自己的东西而不引用来源来增加额外的限制),那将在 GitHub link 下面。如果代码不能以相同的方式使用,则它不是“向后移植”。如果您尝试以 Python 3 方式使用它而不更改您的代码(使用该函数的客户端代码),您将只有“AttributeError:'tuple' 对象没有属性 'returncode'”。您可以更改您的代码,但它不会与 Python 3.

兼容

无论哪种方式,接受的答案中的代码本身都不会 运行 由于:

  1. "TypeError: init() 得到了一个意外的关键字参数 'stderr'"(因为 stderr 不是“CalledProcessError”的参数2 或 3)

  2. "AttributeError: 'Popen' object has no attribute 'args'" (args is only available in Python 3)

因此,考虑更改已接受的答案。

通过利用 duck typing 和 monkey patching 来变得更 Pythonic(您的客户端代码可以保持不变,并对 运行 方法和返回的对象的方法使用如下所示的不同定义class), 这里有一个实现兼容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)。

注意:class 没有相同的 repr 字符串并且可能有其他细微差别(您可以使用 Python 中的真实代码3 本身根据其许可证在以下 URL 中——参见 class CalledProcess in: https://github.com/python/cpython/blob/master/Lib/subprocess.py ——如果有的话,该许可证也适用于我的代码,但我将其作为 CC0 发布,因为它是我认为微不足道的——见上面括号中的解释)。

#IRejectTheInvalidAutomaticLicenseForMyPost