使用subprocess.check_output运行flake8

问题描述 投票:0回答:1

我正在尝试制作一个基本的linter脚本,该脚本可以在当前目录中的Python文件上运行。到目前为止,我的脚本看起来像这样:

import subprocess
from os import listdir
from os.path import isfile, join

if __name__ == "__main__":
    subprocess.check_output(["black", "-l", "100", "./"])

    files = [f for f in listdir("./") if isfile(join("./", f))]
    for file in files:
        if file.endswith(".py"):
            subprocess.check_output(["flake8", file])

我想通过命令行使用main.py之类的代码来运行代码。 Black的表现不错,可以在当前目录中找到。py文件并对其进行格式化,而不会出现问题。但是,当尝试使用flake8运行类似命令时,它也会在我不感兴趣的目录的子目录下运行,例如venv文件夹。

因此,脚本包括检查以获取当前目录中的文件,然后找到。py文件。但是,一旦获得这些文件,我似乎无法将flake8命令与subprocess.check_output一起使用。我得到的错误如下:

Traceback (most recent call last):
  File "linter.py", line 18, in <module>
    subprocess.check_output(["flake8", file], shell=False)
  File "C:\Users\calum\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 411, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "C:\Users\calum\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 512, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['flake8', 'flask_server_controller.py']' returned non-zero exit status 1.

有人可以解释错误和/或为我的问题提供解决方案。我还想在脚本中添加其他整理工具,例如pylint,但是,我担心如果没有正确理解它也会遇到相同的问题。

谢谢。

python subprocess flake8
1个回答
0
投票

subprocess.check_output由于check_的原因而向您提供

这意味着当您正在运行的可执行文件返回非零值(例如,flake8在检测到棉绒故障时返回非零值时,将引发异常)

为了避免这种行为,我建议改用subprocess.run,并沿返回代码转发。像这样的东西:

import os
import subprocess
import sys


def main():
    ret = 0
    output = b''
    for filename in os.listdir('.'):
        if filename.endswith('.py'):
            proc_ret = subprocess.run(
                ('flake8', filename),
                stdout=subprocess.PIPE,
            )
            ret |= proc_ret.returncode
            output += proc_ret.stdout
    sys.stdout.buffer.write(output)
    return ret


if __name__ == '__main__':
    exit(main())

请注意,这将prohibitive缓慢,您必须为每个文件支付flake8的启动成本。

您可以通过将所有文件名一次传递到flake8来改善这一点的一种方法:

import os
import subprocess
import sys


def main():
    filenames = (fname for fname in os.listdir('.') if fname.endswith('.py'))
    proc_ret = subprocess.run(('flake8', *filenames), stdout=subprocess.PIPE)
    sys.stdout.buffer.write(proc_ret.stdout)
    return proc_ret.returncode


if __name__ == '__main__':
    exit(main())

但这又提出了另一个有趣的观点,为什么您要收集所有输出?如果让输出进入标准输出,它将自动打印:

import os
import subprocess


def main():
    filenames = (fname for fname in os.listdir('.') if fname.endswith('.py'))
    return subprocess.call(('flake8', *filenames))


if __name__ == '__main__':
    exit(main())

和hmmm,您可能根本不需要这样做,因为flake8有其自己的包含/排除代码-您可能只想正确配置exclude

# setup.cfg / tox.ini / .flake8
[flake8]
# for example, exclude recursing into the venv
exclude = venv

然后您可以照常使用flake8 .

(免责声明:我是flake8的当前维护者)

© www.soinside.com 2019 - 2024. All rights reserved.