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

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

An older part of our codebase has a function for converting a data structure to XML, using XML::Simple (for some legacy reason), and saving it to a directory.

At some point, we upgraded XML::Simple to 2.24, and it started throwing "Use of uninitialized value" errors. Whatever caused this was irrelevant to our purposes, so I put this in a block with "no warnings 'uninitialized';", and all was good.

For no reason that I can tell--I didn't upgrade any package, or my Perl version (5.16.3 for this)--our test suite is now throwing the error again, though the "no warnings" is right there:

use XML::Simple; my $xml; { # Suppress warnings from XML::Simple 2.24 no warnings 'uninitialized'; my $xmlout = XMLout($data, NoAttr => 1, RootName => undef, Suppres +sEmpty => 0); $xml = '<xml version="1.0" encoding="UTF-8">' . "\n$xmlout</xml>"; }
Result from test suite:
Use of uninitialized value at /[path/to]/Data.pm line 205. Use of uninitialized value at /[path/to]/Data.pm line 205. Use of uninitialized value at /[path/to]/Data.pm line 205. [...]
Where line 205 is the "my $xmlout..." from above.

Can someone explain why I am getting a warning that I explicitly shut off on the immediately preceding line? And how I stop this? The tests pass, but it's distracting as hell to get 50 lines of this error every time we run it.

Replies are listed 'Best First'.
Re: "no warnings 'uninitialized'" failing
by LanX (Saint) on Oct 16, 2017 at 14:18 UTC
    I'm confused, warnings - like most pragmas - is lexically scoped˛, you can't switch off a warning inside another module.

    If Data.pm is your file, I'd clarify first if $data is really not initialized.

    NB: it's possible (and easily implemented) that a module delegates the warning line and file to the caller, probably that's what XML::Simple is doing. *

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

    update

    *) At least it's using Carp

    ˛) from warnings : This means that the scope of the warning pragma is limited to the enclosing block. It also means that the pragma setting will not leak across files (via use, require or do). This allows authors to independently define the degree of warning checks that will be applied to their module. (emphasis added)

Re: "no warnings 'uninitialized'" failing
by haukex (Archbishop) on Oct 16, 2017 at 14:16 UTC

    Have you determined which of the values it is complaining about (is it maybe RootName => undef, or $data as LanX pointed out)? Have you tried any alternatives, i.e. making sure you're not feeding the function undefs where you shouldn't be? Note the effect of warnings is lexical in scope, so it won't change anything coming from inside of XML::Simple. If that is the case, and you're feeding the function valid data, you could try the following ugly hack to suppress all warnings from inside XMLout (although it's about as ugly as using XML::Simple for XML output in the first place...): my $xmlout = do { local $SIG{__WARN__}=sub{}; XMLout(...) };

    Minor edits for clarification.

Re: "no warnings 'uninitialized'" failing
by Mr. Muskrat (Canon) on Oct 16, 2017 at 18:53 UTC

    It looks like $data is undefined.

    #!/bin/env perl use strict; use warnings; use XML::Simple; # From https://metacpan.org/pod/XML::Simple#QUICK-START my $data = { 'logdir' => '/var/log/foo/', 'debugfile' => '/tmp/foo.debug', 'server' => { 'sahara' => { 'osversion' => '2.6', 'osname' => 'solaris', 'address' => [ '10.0.0.101', '10.0.1.101' ] }, 'gobi' => { 'osversion' => '6.5', 'osname' => 'irix', 'address' => [ '10.0.0.102' ] }, 'kalahari' => { 'osversion' => '2.0.34', 'osname' => 'linux', 'address' => [ '10.0.0.103', '10.0.1.103' ] } } }; print "XMLout with data defined:\n\n", xml_out($data), "\n\n"; #print "XMLout with data undefined:\n\n", xml_out(undef), "\n\n"; sub xml_out { my $data = shift; my $xmlout = XMLout($data, NoAttr => 1, RootName => undef, SuppressE +mpty => 0); return '<xml version="1.0" encoding="UTF-8">' . "\n$xmlout</xml>"; }

    Running this produces no warning but if you uncomment the second print it does.

Re: "no warnings 'uninitialized'" failing
by jest (Pilgrim) on Oct 16, 2017 at 20:48 UTC

    Thank you for the replies.

    I'm not sure I realized that "no warnings" wouldn't affect warnings emitted by XML::Simple. I think I knew this in the back of my head, but I added that at some point and it must have worked--perhaps accidentally, combined with some other change--so I never considered it.

    I also don't know why the warnings re-started recently.

    In any case, I'm absolutely sure that $data itself was defined.

    However, after a bunch more testing, I realized that I was getting these warnings for any undefined values in the data. And then I realized that the error was that SuppressEmpty => 0 was a mistake--it's supposed to be SuppressEmpty => undef (or the empty string). When I made this change, the warnings went away, and I got my desired empty XML in the output.

    I have no idea why it (seemed to) work at one point and then go back to not working. However, it's clear that the SuppressEmpty setting was the right way to fix it.

    Thanks again.

      Hmm, it looks weird that a boolean switch should accept 1 but not 0. (???)

      So I took a look into the documentation. ...

      Turns out that  SuppressEmpty is not a real flag, but that "" and undef are used to define how empty elements are represented or ignored in a case of a true value.

      And the docs explicitly talk about "suppressing the generation of warnings" in XMLout().

      I find the naming and concept too error prone.

      Something like  RepresentEmpty => "off" | "" | undef might have been a better choice.

      And I'm understanding even better now, why this module is discouraged, even in its own POD.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

Re: "no warnings 'uninitialized'" failing
by Anonymous Monk on Oct 17, 2017 at 03:37 UTC
    Don't monkey-patch code to make messages go away ... find and fix the underlying bug.