invoking pylint programmatically

后端 未结 7 841
难免孤独
难免孤独 2020-12-05 00:21

I\'d like to invoke the pylint checker, limited to the Error signalling part, as part of my unit testing. so I checked the pylint executable script, got to the pylint

相关标签:
7条回答
  • 2020-12-05 00:41

    Here is a wrapper I use to programmatically call pylint so I have a --fail-under arg to overwite the default pylint exit code (usefull for CI). This snippet was tested using pylint 2.3.1

    """ Execute pylint and fail if score not reached. """
    import argparse
    import sys
    from pylint import lint
    
    desc = "PyLint wrapper that add the --fail-under option."\
           " All other arguments are passed to pylint."
    parser = argparse.ArgumentParser(description=desc, allow_abbrev=False)
    parser.add_argument('--fail-under', dest='threshold', type=float, default=8,
                        help='If the final score is more than THRESHOLD, exit with'
                        ' exitcode 0, and pylint\'s exitcode otherwise.')
    
    args, remaining_args = parser.parse_known_args()
    
    threshold = args.threshold
    
    run = lint.Run(remaining_args, do_exit=False)
    score = run.linter.stats['global_note']
    
    if score < threshold:
        sys.exit(run.linter.msg_status)
    
    0 讨论(0)
  • 2020-12-05 00:45

    Another entry point for pylint is the epylint.py_run function, that implement the stdout and stderr interception. However, as shown in the following code, pylint seems to not write its reports in stdout:

    from pylint import epylint
    
    pylint_stdout, pylint_stderr = epylint.py_run(__file__, return_std=True)
    print(pylint_stdout.getvalue())  # -> there is just the final rank, no report nor message
    print(pylint_stderr.getvalue())
    

    Now, i found that pylint from API and pylint from CLI do not use the same default parameters. So, you just have to provides the parameters you need to pylint.

    from pylint import epylint
    options = '--enable=all'  # all messages will be shown
    options += '--reports=y'  # also print the reports (ascii tables at the end)
    
    pylint_stdout, pylint_stderr = epylint.py_run(__file__ + ' ' + options, return_std=True)
    print(pylint_stdout.getvalue())
    print(pylint_stderr.getvalue())
    

    As described here, pylint will perform the parsing itself, and will correctly output the expected results in stdout.

    0 讨论(0)
  • 2020-12-05 00:51

    I'm glad I came across this. I used some of the answers here and some initiative to come up with:

    # a simple class with a write method
    class WritableObject:
        def __init__(self):
            self.content = []
        def write(self, string):
            self.content.append(string)
    pylint_output = WritableObject()
    
    pylint = lint.Run(args, reporter=ParseableTextReporter(pylint_output), exit=False)
    

    Args in the above is a list of strings eg. ["-r", "n", "myfile.py"]

    0 讨论(0)
  • 2020-12-05 00:55

    I got the same problem recently. syt is right, pylint.epylint got several methods in there. However they all call a subprocess in which python is launched again. In my case, this was getting quite slow.

    Building from mcarans answer, and finding that there is a flag exit, I did the following

    class WritableObject(object):
        "dummy output stream for pylint"
        def __init__(self):
            self.content = []
        def write(self, st):
            "dummy write"
            self.content.append(st)
        def read(self):
            "dummy read"
            return self.content
    def run_pylint(filename):
        "run pylint on the given file"
        from pylint import lint
        from pylint.reporters.text import TextReporter
        ARGS = ["-r","n", "--rcfile=rcpylint"]  # put your own here
        pylint_output = WritableObject()
        lint.Run([filename]+ARGS, reporter=TextReporter(pylint_output), exit=False)
        for l in pylint_output.read():
            do what ever you want with l...
    

    which is about 3 times faster in my case. With this I have been going through a whole project, using full output to check each source file, point errors, and rank all files from their note.

    0 讨论(0)
  • 2020-12-05 00:55

    NOTE: At some point pylint changed the interface. The above examples need to replace exit=False with do_exit=False. (@mad7777, @amit-tripathi)

    (Learned as per https://github.com/carsongee/pytest-pylint/issues/80)

    0 讨论(0)
  • 2020-12-05 00:56

    Instead of creating a WritableObject class we can use StringIO. StringIO contains write method.

    import sys
    try:
        from io import StringIO
    except:
        from StringIO import StringIO
    
    stdout = sys.stdout
    sys.stdout = StringIO()
    
    ARGS = ["-r","n", "--rcfile=rcpylint"]
    r = lint.Run(['../test.py']+ARGS, exit=False)
    
    test = sys.stdout.getvalue()
    sys.stdout.close()
    sys.stdout = stdout
    
    print (test.split('\n'))
    

    Source:

    • @cdarke 's answer

    • @mad7777's answer

    0 讨论(0)
提交回复
热议问题