2017-08-08 23 views
5

widzę ostrzeżenie, jak to w moim dzienników:StackTrace dla UserWarning

py.warnings.__init__: WARNING .../bs4/__init__.py:219: UserWarning: "foo" 
    looks like a filename, not markup. You should probably open this file 
    and pass the filehandle into Beautiful Soup 

Ta wiadomość nie pomaga bardzo.

Chciałbym zobaczyć ślad stosu tam, gdzie to się dzieje.

Proszę nie zaglądać w treść tego ostrzeżenia. To pytanie nie jest o pięknych Soup :-)

Prostym rozwiązaniem byłoby zmodyfikować kod trzeciej partii (bs4/__init__.py na linii 219) i dodać coś takiego:

import traceback 
logger.warn('Exc at ...\n%s' % ''.join(traceback.format_stack())) 

ale chciałbym, aby uniknąć to. Powody:

  • To ostrzeżenie od systemu produkcyjnego. Nie chcę zmieniać źródła.
  • Następnym razem ostrzeżenie jak to nastąpi, chciałbym zobaczyć StackTrace natychmiast

Czy istnieje flagi lub ustawienie dla Pythona, które mogę zmienić, aby zobaczyć nie tylko jedną linię, ale jednocześnie StackTrace ? Potrzebuję górnych ramek do debugowania tego.

W tym środowisku Python 2.7 zostaje wykorzystany.

Odpowiedz

2

będzie trzeba wykonać następujące czynności:

  1. Tworzenie jeśli USER_SITE nie istnieje: problem python -c "import site; site._script()" patrz USER_SITE zmiennej zawartości
  2. Umieść plik usercustomize.py w tym katalogu z następującego kodu:

    import traceback 
    import warnings 
    
    
    _old_warn = warnings.warn 
    def warn(*args, **kwargs): 
        tb = traceback.extract_stack() 
        _old_warn(*args, **kwargs) 
        print("".join(traceback.format_list(tb)[:-1])) 
    warnings.warn = warn 
    

    Kredyty na this odpowiedź na kod.

Uruchom kod jak zwykle. Mój kod testowy:

import warnings 

def f(): 
    warnings.warn("foz") 

f() 

Przed zabiegiem:

$ python test_warn.py 
test_warn.py:4: UserWarning: foz 
    warnings.warn("foz") 

Po:

$ python test_warn.py 
<USER_SITE_REDACTED>/usercustomize.py:6: UserWarning: foz 
    _old_warn(*args, **kwargs) 
    File "test_warn.py", line 6, in <module> 
    f() 
    File "test_warn.py", line 4, in f 
    warnings.warn("foz") 
+0

OK, rozumiem. AFAIK to tak zwane łatanie małp. Tak, myślę, że usercustomize.py jest dobrym miejscem do łatania małp w ten sposób. Dziękuję Ci. – guettli

+1

@guettli, jest monkeypatching. Chociaż może to być uzasadniony przypadek użycia go, biorąc pod uwagę, że źródło nie może zostać zmienione, a ingerencja nie zmienia żadnej logiki - po prostu skutecznie dodaje więcej rejestrowania. – RebelWithoutAPulse

1

Jeśli chcę znaleźć korzeń ostrzeżeniem ja generalnie tylko do promowania WarningsExceptions.

W twoim przypadku możesz po prostu użyć warnings.simplefilter lub warnings.filterwarnings.

Na przykład:

import warnings 

def func(): 
    warnings.warn('abc', UserWarning) 

def func2(): 
    func() 

# Here I promote all UserWarnings to exceptions, but you could also use "warnings.filterwarnings" 
# to only promote warnings from a specified module or matching a specified message. 
# You may need to check which is most useful/appropriate for you. 
warnings.simplefilter("error", UserWarning) # you might need to reset this later :) 
func2() 

co daje całościowy traceback:

--------------------------------------------------------------------------- 
UserWarning        Traceback (most recent call last) 
<ipython-input-11-be791e1071e7> in <module>() 
     8 
     9 warnings.simplefilter("error", UserWarning) 
---> 10 func2() 

<ipython-input-11-be791e1071e7> in func2() 
     5 
     6 def func2(): 
----> 7  func() 
     8 
     9 warnings.simplefilter("error", UserWarning) 

<ipython-input-11-be791e1071e7> in func() 
     2 
     3 def func(): 
----> 4  warnings.warn('abc', UserWarning) 
     5 
     6 def func2(): 

UserWarning: abc 

A jeśli chcesz debugować ten można łatwo zaczepić pytony pdb s na ostatniej napotkanego wyjątek:

import pdb 

pdb.pm() 

w wyniku czego:

> <ipython-input-11-be791e1071e7>(4)func() 
-> warnings.warn('abc', UserWarning) 
(Pdb) _________________ 

Rozpoczyna analizę pośmiertną ostatniego napotkanego wyjątku. Które powinny umożliwić Ci kopać przez ramek i sprawdzić zmienne itp


też poproszony o fladze i rzeczywiście tam jest flaga, która umożliwia obsługę „ostrzegawczy”, to -W flag. To bardzo przypomina funkcję warnings.filterwarnings. Dla wygody po prostu kopiowane z dokumentacją -W flagą tutaj:

Warning control. Python’s warning machinery by default prints warning messages to sys.stderr. A typical warning message has the following form:

file:line: category: message 

By default, each warning is printed once for each source line where it occurs. This option controls how often warnings are printed.

Multiple -W options may be given; when a warning matches more than one option, the action for the last matching option is performed. Invalid -W options are ignored (though, a warning message is printed about invalid options when the first warning is issued).

Starting from Python 2.7, DeprecationWarning and its descendants are ignored by default. The -Wd option can be used to re-enable them.

Warnings can also be controlled from within a Python program using the warnings module.

The simplest form of argument is one of the following action strings (or a unique abbreviation) by themselves:

  • ignore

    Ignore all warnings.

  • default

    Explicitly request the default behavior (printing each warning once per source line).

  • all

    Print a warning each time it occurs (this may generate many messages if a warning is triggered repeatedly for the same source line, such as inside a loop).

  • module

    Print each warning only the first time it occurs in each module.

  • once

    Print each warning only the first time it occurs in the program.

  • error:

    Raise an exception instead of printing a warning message.

The full form of argument is:

action:message:category:module:line 

Here, action is as explained above but only applies to messages that match the remaining fields. Empty fields match all values; trailing empty fields may be omitted. The message field matches the start of the warning message printed; this match is case-insensitive. The category field matches the warning category. This must be a class name; the match tests whether the actual warning category of the message is a subclass of the specified warning category. The full class name must be given. The module field matches the (fully-qualified) module name; this match is case-sensitive. The line field matches the line number, where zero matches all line numbers and is thus equivalent to an omitted line number.

+0

Myślę, że to nie jest adresowane w twojej anwerze: Następnym razem, gdy pojawi się takie ostrzeżenie, chciałbym natychmiast zobaczyć stacktrace. – guettli

+0

Natychmiast zobaczysz traceback, jeśli promujesz je do wyjątków. A może źle zrozumiałem twoje pytanie? – MSeifert

+0

Źle zrozumiałem twoje rozwiązanie. Myślę, że teraz to zrozumiałem. "Wywołaj wyjątek zamiast drukowania ostrzeżenia." Chciałbym tego uniknąć, ponieważ ostrzeżenie dzieje się w środowisku produkcyjnym i do tej pory nie jest ono powtarzalne w środowisku programistycznym. Chciałbym uniknąć w tym przypadku przejścia od ostrzeżenia do wyjątku. – guettli