http://qs321.pair.com?node_id=1051133

citromatik has asked for the wisdom of the Perl Monks concerning the following question:

Is there a way to prevent a warning message produced in a module from a client script? i.e. something like this:

use RandomModule; { no warnings; RandomModule::doSomethingThatCanGenerateWarnings(); }

RandomModule uses "use warnings"

citromatik

Replies are listed 'Best First'.
Re: no module warnings in client code
by kennethk (Abbot) on Aug 27, 2013 at 13:46 UTC
    There are missing variables here, such as is this a module you maintain, is it emitting warnings directly or using Carp or other secondary module, does your suggested code work?

    In general, the easiest and most appropriate way to silence warnings is to address what the warning is complaining about. Assuming you don't want to do that, your code above would work, assuming that the module does not implement its own warning control. If it does, you can cheat by locally clobbering the warning handler:

    { local $SIG{__WARN__} = sub {#Drop it}; RandomModule::doSomethingThatCanGenerateWarnings(); }

    Update: Added some <del> tags following a node update.


    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      Hi kennethk

      My suggested code doesn't work... If it had worked I wouldn't have asked!

      Here is a testing code:

      Package:

      package tt; use strict; use warnings; sub w { my $str = ""; return substr ($str, 10, 10); } 1;

      Client script:

      use strict; use tt; print tt::w();

      Defining a local warning handler works perfectly:

      use strict; use tt; local $SIG{__WARN__} = sub {}; print tt::w();

      Thanks for the help

      citromatik

        Hi citromatik,
        And you might want to but local $SIG{__WARN__} = sub{}; into a block like kennethk did it.
        If not, you would not receive any other warnings from your client script.
        Just saying ...
        If you tell me, I'll forget.
        If you show me, I'll remember.
        if you involve me, I'll understand.
        --- Author unknown to me
Re: no module warnings in client code
by kcott (Archbishop) on Aug 27, 2013 at 14:55 UTC

    G'day citromatik,

    In the first instance, you'd probably want to consider why you don't want to see the warnings. Can you rewrite your code so that you don't get warnings in the first place? I'd also question why you want to prevent all warnings (i.e. with no warnings;) rather than just a specific warning (e.g. no warnings 'once';). If you think that the warnings that are emitted are in some way wrong, can you raise a bug report? Can you tell us what actual module you're dealing with? — perhaps we can suggest a fix for your code or some other workaround.

    Given this module:

    package Bad; use warnings; sub gen_warning { print "Undeclared: >>>$x<<<"; } 1;

    There's clearly a bug (albeit highly contrived) which should be fixed.

    Using it normally:

    $ perl -le ' use Bad; Bad::gen_warning(); ' Use of uninitialized value $Bad::x in concatenation (.) or string at B +ad.pm line 6. Undeclared: >>><<<

    Looking at the documentation for the warnings pragma, you'll see:

    "The warnings pragma is a replacement for the command line flag -w, but the pragma is limited to the enclosing block, ..." [my strong emphasis]

    This is why your posted "something like this" suggestion doesn't work:

    $ perl -le ' use Bad; { no warnings; Bad::gen_warning(); } ' Use of uninitialized value $Bad::x in concatenation (.) or string at B +ad.pm line 6. Undeclared: >>><<<

    However, as an interim measure, you could do something like this:

    $ perl -le ' use Bad; { no warnings "redefine"; sub Bad::gen_warning { use warnings "redefine"; no warnings "uninitialized"; print "Undeclared: >>>$x<<<"; } } Bad::gen_warning(); ' Undeclared: >>><<<

    Notice how I turned off one specific warning to redefine the subroutine; that particular warning is switched back on inside the subroutine (obviously unnecessary for this simple example: I'm making a point about affecting the smallest possible scope when doing this). Also, inside the subroutine, only one specific type of warning is turned off.

    Probably the biggest problem with that is you'll always be stuck with your version! When the offending subroutine is fixed, enhanced, extended or otherwise modified, your code will continue to use your redefinition.

    If you provide more information about your specific issue, perhaps we can suggest a better way to deal with it.

    -- Ken