得到错误 - AttributeError:' module'对象没有属性' run'运行subprocess.run([" ls"," -l"])

时间:2016-11-14 13:44:59

标签: python python-2.7 subprocess aix

我在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'

2 个答案:

答案 0 :(得分:27)

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

然而,向后移动很容易:

def run(*popenargs, input=None, check=False, **kwargs):
    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

不支持超时,也没有完成流程信息的自定义类,因此我只返回retcodestdoutstderr信息。否则它与原始版本完全相同。

答案 1 :(得分:0)

接受的答案是非工作代码,并且与原始 (Python 3) 函数的返回值不同。然而,它足够相似,它不是 CC BY 4.0 Martijn Pieters,因为它是从 Python 复制的,如果任何许可证适用于琐碎代码(我完全反对对琐碎代码进行许可,因为它阻碍了创新和证明所有权或原创性)是困难的,因此 stackoverflow 可能会违反包括 GPL 在内的各种许可证,方法是通过重新许可人们粘贴的东西并默认为他们自己的东西而不引用来源来添加额外的限制),这将在下面的 GitHub 链接中。如果代码不能以相同的方式使用,则它不是“向后移植”。如果您尝试在不更改代码(使用该函数的客户端代码)的情况下以 Python 3 方式使用它,您将只有“AttributeError: 'tuple' object has no attribute 'returncode'”。您可以更改您的代码,但它将与 Python 3 不兼容。

无论如何,接受的答案中的代码本身甚至不会运行,因为:

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

  2. “AttributeError: 'Popen' 对象没有属性 'args'”(args 仅在 Python 3 中可用)

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

为了通过利用鸭子类型和猴子补丁来更加 Pythonic(您的客户端代码可以保持不变,并为 run 方法和返回的对象的类使用如下所示的不同定义),这里是一个兼容的实现蟒蛇 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