Próbuję się dowiedzieć, jak działa aplikacja. W tym celu wstawiam polecenia debugowania jako pierwszy wiersz treści każdej funkcji w celu zarejestrowania nazwy funkcji, a także numeru wiersza (w kodzie), w którym wysyłam wiadomość do wyjścia dziennika. Wreszcie, ponieważ ta aplikacja składa się z wielu plików, chcę utworzyć pojedynczy plik dziennika, aby lepiej zrozumieć przepływ sterowania w aplikacji.
Oto co wiem:
aby uzyskać nazwę funkcji, mogę użyć,
function_name.__name__
ale nie chcę używać funkcji nazwa_funkcji (aby móc szybko skopiować i wkleić rodzaj ogólnyLog.info("Message")
w treści wszystkich funkcji). Wiem, że można to zrobić w C przy użyciu__func__
makra, ale nie jestem pewien co do Pythona.aby uzyskać nazwę pliku i numer linii, widziałem, że (i uważam, że) moja aplikacja używa
locals()
funkcji Pythona, ale w składni, której nie jestem do końca świadomy, np.:options = "LOG.debug('%(flag)s : %(flag_get)s' % locals())
i próbowałem użyćLOG.info("My message %s" % locals())
czegoś podobnego, który daje coś podobnego{'self': <__main__.Class_name object at 0x22f8cd0>}
. Jakieś uwagi w tej sprawie?Wiem, jak używać rejestrowania i dodawać do niego program obsługi, aby logować się do pliku, ale nie jestem pewien, czy pojedynczy plik może być użyty do zapisania wszystkich komunikatów dziennika we właściwej kolejności wywołań funkcji w projekcie.
Byłbym bardzo wdzięczny za każdą pomoc.
Dzięki!
import pdb; pdb.set_trace()
przejść do debugera języka Python za pomocą , a następnie interaktywnie przechodzić przez kod. Może to pomóc w śledzeniu przepływu programu.Odpowiedzi:
Masz tutaj kilka marginalnie powiązanych pytań.
Zacznę od najłatwiejszego: (3). Używając
logging
you możesz zagregować wszystkie wywołania do pojedynczego pliku dziennika lub innego celu wyjściowego: będą one w kolejności, w jakiej wystąpiły w procesie.Dalej: (2).
locals()
zawiera dyktando aktualnego zakresu. Tak więc w metodzie, która nie ma innych argumentów, maszself
zakres, który zawiera odwołanie do bieżącego wystąpienia. Sztuczka używana, która cię przytłacza, polega na formatowaniu łańcucha przy użyciu dyktowania jako prawej strony%
operatora."%(foo)s" % bar
zostanie zastąpiony jakąkolwiek wartościąbar["foo"]
.Na koniec możesz użyć kilku sztuczek introspekcji, podobnych do tych używanych przez
pdb
to, aby zarejestrować więcej informacji:Spowoduje to zarejestrowanie przekazanego komunikatu plus (oryginalna) nazwa funkcji, nazwa pliku, w którym pojawia się definicja oraz wiersz w tym pliku. Spójrz na Inspect - Zbadaj obiekty na żywo, aby uzyskać więcej szczegółów.
Jak wspomniałem wcześniej w moim komentarzu, możesz również
pdb
w dowolnym momencie przejść do interaktywnego monitu o debugowanie, wstawiając wierszimport pdb; pdb.set_trace()
i ponownie uruchamiając program. Umożliwia to przechodzenie przez kod, sprawdzanie danych według własnego uznania.źródło
'%(foo)s : %(bar)s'
wypisałby również wartośćbar["foo"]
's? A może trochę różni się od twojego przykładu?%(<foo>)s
jest zastępowane przez wartość obiektu, do którego odwołuje się dykt<foo>
. Więcej przykładów / szczegółów można znaleźć na stronie docs.python.org/library/stdtypes.html#string-formattingPrawidłową odpowiedzią na to jest użycie już podanej
funcName
zmiennejNastępnie, gdziekolwiek chcesz, po prostu dodaj:
Przykładowe dane wyjściowe ze skryptu, nad którym teraz pracuję:
źródło
getLogger(__name__)
logging.getLogger('root')
prawdopodobnie nie jest tym, czego się spodziewasz, to nie jestroot
rejestrator, ale zwykły rejestrator o nazwie „root”.funcname
,linename
Ilineno
dostarczają informacji o ostatniej funkcji, która zrobiła to rejestrowanie.Jeśli masz opakowanie loggera (np. Singleton logger), odpowiedź @ synthesizerpatel może nie działać dla Ciebie.
Aby znaleźć innych dzwoniących w stosie połączeń, możesz:
źródło
logging
poziomu klasy obsługuje stos omijając out-of-the-box: Metody podobalog()
,debug()
itd teraz przyjąćstacklevel
argumentu. Zobacz dokumentację .