Głowny problem
Mam jakiś skrypt python uruchamiany przez Jenkins-a, który robi jakieś cuda: Skanuję dużą ilość plików i generuje uproszony raport.
Jak coś pójdzie nie tak i leci wyjątek, to chce by niektóre funkcje logowały, jakie dostały argumenty, żeby było łatwo ustalić co włąściwie poszło nie tak.
W moim przypadku chodzi o to by było wiadomo, który plik xml jest niepoprawny.
Próba rozwiązania
w związku z tym naskrobałem coś takiego:
def log_argument_on_exception(func):
"""Decorator that logs the argument value if an exception is raised."""
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"{func.__name__}({', '.join(map(repr, args))})")
raise e
return wrapper
Funkcja z tym dekoratorem jak rzuca wyjątek to wypisuje np:
parse_xml(WindowsPath('../Rules/Exclusions/Microsoft, Various services - [B1002].xml'))
Problem
Powyższy kod działa bardzo dobrze. W moim przypadku sprawdza się wzorcowo.
Problem polega na tym, że rozwiązanie nie jest dostatecznie uniwersalne, żebym był zadowolony.
Nie wypisuje zawartości **kwargs
, wiec jeśli udekorowana funkcja wygląda tak:
@log_argument_on_exception
def magic(path, *, option=None):
...
To informacja option
nie zostanie wypisana :(.
Taka próba poprawiania (która się wydawała rozsądna), psuje cały kod (normalne argumenty przestają działać):
print(f"{func.__name__}({', '.join(map(repr, args, kwargs))})")
Próbowałem na inne sposoby z gorszym rezultatem.
Pytanie
Czy da się w jakiś elegancki sposób dodać informację o nazwanych argumentach?
Chcę by kod był pythonic, nie chcę dużego boiler plate code (w ten sposób to potrafię to zrobić sam).
Minimalny Python 3.8.