mailRe: RelaxWarnings


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by Edward d'Auvergne on August 16, 2006 - 19:16:
> relax> import warnings
> relax> def format(message, category, filename, lineno):
> relax|     return "RelaxWarning: %s\n" % message
> relax|
> relax> warnings.formatwarning = format
> relax> warnings.warn('Hello')
> RelaxWarning: Hello
> relax> help(warnings.formatwarning)
> relax> warnings.warn('Hello')
> relax>
>
> Huh???  Where did RelaxWarning disappear to??? Same thing happens if
> you use the real Python help function on any 'warnings' objects,
> including itself???  I'm pretty sure this should not happen!

I think the problem is that the default warning behaviour is to print a
given warning only once from a specific location in the code. Because
you are working at the interactive prompt, it always looks like the same
location, so the warning will only be printed once (it has nothing to do
with help). Try:

relax> import warnings
relax> warnings.filterwarnings('always')
relax> def format(message, category, filename, lineno):
relax|     return "RelaxWarning: %s\n" % message
relax|
relax> warnings.formatwarning = format
relax> warnings.warn('Hello')
RelaxWarning: Hello
relax> help(warnings.formatwarning)
relax> warnings.warn('Hello')
RelaxWarning: Hello

Of course! I should have seen that one.

> If there are too many problems caused by bugs in the Python warning
> system we can write our own warning system in the future.  Anyway,
> enough bashing of the Python warning system.
>
> A problem that needs to be solved is how do we implement specific
> warnings?  For example if two distant areas of relax test for zero
> length XH bond vectors, there should be one function which takes the
> residue number and formats a standard message for that warning.
> However the 'warn()' function expects a message?  What if we have a
> class object called RelaxZeroLengthWarning which has a __call__()
> method which returns the formatted string?  You could then, from
> within different parts of relax, generate an error by having the code:
>
> if len(xh) == 0.0:
>     warn(RelaxZeroLengthWarning(res))
>
> where warn was placed into __builtin__ by relax (see the
> 'nan_catch_test' branch) and 'res' is the residue number.  There
> might, however, be a much better way to implement specific warnings.
> The rest of the system could be setup as in the 'nan_catch_test'
> branch.
>

This is a good point. After some head-scratching, I think the 'correct'
way to do it is to treat each warning category specifically in the
formatwarning function. So we would have something more like:

def format(message, category, filename, lineno):
    if issubclass(category, RelaxZeroLengthWarning):
        message = "Zero length vector at residue %s" % message

    # ...lots more specific warning cases...

    if issubclass(category, BaseWarning):
        message = "RelaxWarning: %s\n" % message

    return message

warnings.formatwarning = format


Then the 'message' for RelaxZeroLengthWarning when we do warn() is just the residue, and format() does the rest.

A number of RelaxErrors take a number of arguments and from my reading of the docs I would guess that the warning system would assert that the 'message' argument to 'warn()' must be a string. How about using the '__call__()' function to pass in the relevant data to the class using keywords and then store it within the object. Then the subsequently called format function can use the else-if chain to pull out and format the stored data?

Edward



Related Messages


Powered by MHonArc, Updated Thu Aug 17 12:40:41 2006