Obsługa szybkiej naprawy śledzenia w Pythonie

18

Powiedzmy, że mam skrypt python z błędem środowiska wykonawczego:

$ cat example.py  
#! /usr/bin/env python3

a = 1/0

co daje:

$ python3 example.py 
Traceback (most recent call last):
  File "example.py", line 3, in <module>
    a = 1/0
ZeroDivisionError: division by zero

Chcę, aby Vim przeskoczył do problematycznej linii tego pliku (w tym przypadku linii 3). Wiem, że Vim może to zrobić, ponieważ działa dobrze do wychwytywania błędów w czasie kompilacji w C przy gccużyciu :makei quickfixokna.

wyjście szybkiej poprawki z gcc

Jasne, mogę wypełnić okno szybkiej poprawki Vima za pomocą, :set makeprg=python3\ %a następnie :make, ale nie przeskakuje on do numeru linii, na który wskazuje ślad. Kiedy patrzę w :copento, po prostu podświetla pierwszą linię śladu i nie mogę przeskoczyć do odpowiedniego numeru linii.

dane wyjściowe poprawki z python3

( jessieW przypadku Debiana korzystam z Vima 7.4 .)

Moje pytania to:

  • Czy mogę skonfigurować Vima, aby wiedział, jak uzyskać odpowiedni numer linii ze śledzenia w Pythonie?

  • Czy mogę zmodyfikować interpreter Pythona, aby wyrzucił format błędu, który Vim już wie, jak analizować i uzyskać odpowiedni numer linii?

Nathaniel M. Beaver
źródło
Możesz sklasyfikować program rejestrujący w skrypcie, aby wygenerować punkty śledzenia po jednym w wierszu (zobacz tutaj, aby zacząć), a następnie errorformatodpowiednio go dostosuj i napisz wtyczkę kompilatora dla Vima (patrz :help :compileri :help write-compiler-plugin). Prawdopodobnie nie warte wysiłku, jeśli nie wiesz dokładnie, co robisz i nie jesteś wystarczająco entuzjastyczny, aby wykopać wszystko z dokumentów.
Sato Katsura
Zadałem podobne pytanie na StackOverflow, możesz znaleźć te odpowiedzi przydatne stackoverflow.com/questions/11333112/...
jalanb

Odpowiedzi:

7

Vim zawiera zestaw skryptów „kompilatora”, z których jeden nazywa się „pyunit” . Jeśli uruchomisz, :compiler pyunita następnie :make(z sugerowaną wartością dla 'makeprg'), poprawka zostanie zapełniona zgodnie z oczekiwaniami. Działa to jednak dobrze tylko wtedy, gdy istnieje jeden poziom śledzenia stosu.

Ulepszenie tego skryptu kompilatora byłoby przydatnym ćwiczeniem.

Rozebranie stosu wtyczki mogą być interesujące, gdyż zapewnia ogólny mechanizm do analizowania i wyświetlać lokalizacje zgłoszone w ślad stosu i posiada wsparcie Pythona wbudowany.

jamessan
źródło
4

Wbudowana wtyczka kompilatora pyunit

Jak już zasugerował jamessan , jedną z opcji jest użycie wbudowanej wtyczki kompilatora pyunit:

:compiler pyunit
:set makeprg=python3\ %
:make

Ma to tę wadę, że zwija ślad stosu do pojedynczego komunikatu o błędzie. Na przykład następujący skrypt Pythona:

def lumberjack():
    bright_side_of_death()

def bright_side_of_death():
    return tuple()[0]

lumberjack()

... wyświetla ten komunikat o błędzie:

|| Traceback (most recent call last):
lumberjack.py|7|  IndexError: tuple index out of range

Pisanie własnej wtyczki kompilatora

Alternatywnie możesz podać własną wtyczkę kompilatora ~/.vim/compiler/python.vim:

if exists("current_compiler")
  finish
endif
let current_compiler = "python"

let s:cpo_save = &cpo
set cpo&vim

CompilerSet errorformat=
      \%*\\sFile\ \"%f\"\\,\ line\ %l\\,\ %m,
      \%*\\sFile\ \"%f\"\\,\ line\ %l,
CompilerSet makeprg=python3\ %

let &cpo = s:cpo_save
unlet s:cpo_save

Wybierz wtyczkę ręcznie za pomocą :compiler pythonlub załaduj ją automatycznie, dodając to do ~/.vim/after/ftplugin/python.vim:

if !exists("current_compiler")
  compiler python
endif

W powyższym skrypcie Pythona Vim zapełnia okno poprawki:

|| Traceback (most recent call last):
lumberjack.py|7| in <module>
||     lumberjack()
lumberjack.py|2| in lumberjack
||     bright_side_of_death()
lumberjack.py|5| in bright_side_of_death
||     return tuple()[0]
|| IndexError: tuple index out of range

Zobacz :help write-compiler-pluginwięcej informacji.

siho
źródło
3

quickfix.py analizuje dane śledzenia w przyjazny dla formatu vim format błędu. Oto przykład uruchomienia go na pliku z pojedynczą linią 1 / 0.

❯❯❯ quickfix.py tests/errors/div_by_zero.py
"tests/errors/div_by_zero.py":1: ZeroDivisionError: division by zero

Domyślnie pokazuje pliki użytkownika, ale może także wyświetlać pliki systemowe (uruchamiając je na pliku zawierającym import os; os.environ['123']):

❯❯❯ quickfix.py -a /tmp/test.py                                                                                                        
"/usr/lib/lib/python3.7/os.py":678: KeyError: '123'
"/tmp/test.py":1: in function <module>

Konfiguracja:

Gdy quickfix.pyjest dostępny w bieżącej ścieżce, dodaj następujące wiersze w vimrc, aby go użyć.

if has("autocmd")
  autocmd FileType python setlocal makeprg=quickfix.py\ %
  autocmd FileType python setlocal errorformat=%E\"%f\":%l:%m,
endif
jadelord
źródło
-1

Nie jest to metoda automatyczna, ale Traceback w Pythonie podaje numer linii --- 3 w twoim przykładzie --- i dlatego wywołuje vim:

$ vim +3 example.py

otworzy example.pykursor w trzecim wierszu.

Chris Hanning
źródło
2
Jestem tego świadomy, ale dotyczy to obsługi Quickfix. Po uruchomieniu :makepliku, który już otworzyłem, szybsze :3jest przejście do trzeciej linii niż zamknięcie i ponowne otwarcie. Robienie tego ręcznie jest również uciążliwe dla bardziej złożonych śladów stosu, dlatego chcę obsługiwać Quickfix.
Nathaniel M. Beaver