簡體   English   中英

出現錯誤 - AttributeError: 'module' 對象在運行 subprocess.run([“ls”, “-l”]) 時沒有屬性 'run'

[英]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()函數僅存在於 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

不支持超時,也沒有用於完成進程信息的自定義類,所以我只返回retcodestdoutstderr信息。 否則它會做與原始相同的事情。

接受的答案是非工作代碼,也沒有與原始(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 () got an unexpected keyword argument 'stderr'”(因為 stderr 不是 2 或 3 中“CalledProcessError”的參數)

  2. “AttributeError: 'Popen' 對象沒有屬性 'args'”(args 僅在 Python 3 中可用)

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

為了通過利用鴨子類型和猴子補丁(您的客戶端代碼可以保持不變並使用如下所示的不同定義用於 run 方法和返回的對象的類)來更加 Pythonic,這里有一個與 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 本身的真實代碼 - 請參閱類 CalledProcess 在:https://github。 com/python/cpython/blob/master/Lib/subprocess.py——如果有的話,該許可證也適用於我的代碼,但我將其發布為 CC0,因為我認為這是微不足道的——請參閱上面括號中的解釋)。

#IRejectTheInvalidAutomaticLicenseForMyPost

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM