2010-01-08 10 views
28

Ich möchte den Pyylint Checker, beschränkt auf den Error-Signalisierung Teil, als Teil meiner Unit-Tests aufrufen. also überprüfte ich das ausführbare pylint-script, kam zu der pylint.lint.Run-helfer-klasse und dort verlor ich mich in einer ziemlich langen __init__ funktion, die mit einem anruf an sys.exit() endete.Aufruf von Pylint programmgesteuert

Wer hat es jemals versucht und geschafft?

würde der Traum-Plan sein:

if __name__ == '__main__': 
    import pylint.lint 
    pylint.lint.something(__file__, justerrors=True) 
    # now continue with unit testing 

irgendwelche Hinweise? anders als "Kopieren Sie die __init__ Methode und überspringen Sie die sys.exit()", meine ich?

ich nicht die Tests müssen von pylint ausgeführt werden, es könnte genauso gut pyflakes oder andere Software sein: gerne Alternativen vorzuschlagen. Vielen Dank!

Antwort

20

Werfen Sie einen Blick auf die pylint/epylint.py, die enthält zwei verschiedene Möglichkeiten, pylint programmatisch zu starten. rufen auch

können Sie einfach:

from pylint.lint import Run 
Run(['--errors-only', 'myfile.py']) 

zum Beispiel.

+0

kombiniert mit der vorherigen Antwort. und mit geringfügiger Änderung: 'pylint.lint.Run (['- Fehler-only', Dateiname])' – mariotomo

+0

gibt es eine Möglichkeit, mehrere Dateien zu analysieren, wenn pylint programmatisch aufgerufen wird? – Gobliins

+0

@gobliins: Ja, füge einfach andere Dateinamen an die Liste an, die als Run-Argument angegeben wurde. – sthenault

3

Ich bin froh, dass ich darauf stieß. Früher habe ich einige der Antworten hier und einige Initiative zu kommen mit:

# 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 der oben ist eine Liste von Strings zB. ["-r", "n", "myfile.py"]

+2

Ich lege eine Lösung oben, aber ich habe seitdem festgestellt, dass Aufruf von Pylint programmatisch auf diese Weise ist schlecht, weil Pylint verwendet Importe, die im Cache gespeichert sind. Wenn Sie also die Datei bearbeitet haben, die Sie gelöscht haben, werden die Änderungen nicht angezeigt. Wenn Sie Pylint nur einmal programmatisch gegen ein einzelnes Skript ausführen, ist das wahrscheinlich in Ordnung. – mcarans

14

Ich habe vor kurzem das gleiche Problem. syt hat recht, pylint.epylint habe mehrere Methoden drin. Sie rufen jedoch alle einen Subprozess auf, in dem Python erneut gestartet wird. In meinem Fall wurde das ziemlich langsam.

Gebäude aus mcarans Antwort, und festgestellt, dass es ein Flag Ausgang ist, habe ich die folgenden

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... 

die etwa 3-mal schneller in meinem Fall ist. Damit habe ich ein ganzes Projekt durchgespielt, wobei ich die gesamte Ausgabe benutzt habe, um jede Quelldatei zu überprüfen, Fehler zu lokalisieren und alle Dateien von ihrer Notiz aus zu ordnen.

+1

Können Sie mich bitte an die Quelle pint, wo ich darüber lesen kann. –

+0

Danke, es funktioniert! Hier ist der Code, der die Ausgabe analysiert und die Bewertung zurückgibt (Sie können gerne die Antwort hinzufügen, wenn Sie möchten): https://pastebin.com/Lta2cCB8 –

+0

Sie verwenden auch: pylint_output = pylint.testutils.TestReporter() und dann die Ergebnisse mit test_reporter.finalize(). strip() erhalten. Oder noch besser, schauen Sie sich die Implementierung von 'TestReporter' an und implementieren Sie Ihre eigenen, um strukturelle Nachrichten zu verarbeiten. –

1

Anstatt eine WritableObject-Klasse zu erstellen, können wir StringIO verwenden. StringIO enthält eine Schreibmethode.

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')) 

Quelle:

0

Ein weiterer Ansatzpunkt für Pylint ist die epylint.py_run Funktion, dass die stdout implementieren und stderr Interception.Wie jedoch in dem folgenden Code dargestellt, scheint Pylint nicht seine Berichte in stdout zu schreiben:

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()) 

Nun fand ich, dass Pylint von CLI und Pylint von CLI nicht die gleichen Standardparameter verwenden. Sie müssen also nur die Parameter angeben, die Sie für pylint benötigen.

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()) 

Wie beschrieben here, Pylint wird das Parsen selbst und korrekt Ausgang der erwarteten Ergebnisse in stdout zuführen.