2012 twenty-four merry days of Perl Feed

Checking Out Your Data Structures

Data::Printer - 2012-12-06

Have Your Variables Been Naughty or Nice?

Every once in a while you expect your variables to contain a certain value, only to realize, sometimes a bit too late, that something's off. We've all been there, and having a way to quickly and neatly view the contents of your variables can make all the difference in the world.

Enter Data::Printer, a module that formats and prints your data structures on screen, in a way that lets you easily check them and spot errors. Its output is colored by default, and it also contains several filters to help you debug objects.

Using it couldn't be simpler: Data::Printer exports a p() function to your namespace that you use to dump your data to STDERR (or anywhere else in fact):

use Data::Printer;

...

p $some_variable;

Since it's a debugging module you'll likely be turning it on and off everywhere in your code. If that's the case, a common idiom is to simply add this line when you need to check some data:

use DDP; p $some_variable;

Which takes advantage of DDP, a shorter alias for Data::Printer.

Optimized for Humans

Now, if you were using it to view the content of a complex data structure, this is what you might get:

\ [     [0] "/path/from/env" (TAINTED),     [1] [         [0] "foo",         [1] "bar"     ],     [2] {         name     "",         gifts    var[1]     },     [3] \ "Some string reference" (weak) ]

Did you see what just happened? Not only did Data::Printer show you the contents of your variable in a clear, colored and indented fashion, it also let you see array indices, know about circular references, tainted data, and weak references, and it can detect and describe many more facts about your data!

But enough about plain data structures. Let's try it with an object:

package My::Class {
  sub new {
    my $class = shift;
    return bless { num => 42 }, $class;
  }

  sub foo {}
  sub bar {}
  sub _baz {}
};

If you use Data::Printer on an instance of the class defined above, you'll see something like this when you dump it:

My::Class {     public methods (3) : bar,foo,new     private methods (1) : _baz     internals: {         num     42     } }

Pretty neat, huh? It would even show inheritance if we had any =)

Filters

Another of Data::Printer's strenghts lies in how it lets you easily filter Perl types and classes. The basic distribution includes formatters for some popular modules like DateTime, Digest and DBI, so if you have enabled them in your settings, then this:

my $data = {
    datetime => DateTime->new( year => 2012, month => 12, day => 25 ),
    dbh => DBI->connect($dsn, $user, $pass),
    digest => Digest::MD5->new,
};

use DDP; p $data;

Might show you something like this:

\ {     datetime    2012-12-25T00:00:00 [floating],     dbh         mysql Database Handle (connected) {         database: mydb         Auto Commit: 1         Statement Handles: 0         Last Statement: -     }     digest    d41d8cd98f00b204e9800998ecf8427e [reset], }

Notice how, in this example, Data::Printer showed you:

  • DateTime objects as formatted strings with the timezone (in this case, 'floating');

  • Database handles with information regarding connection, current database, amount of active statement handles, last run statement and even extra properties that might influence your program (like AutoCommit);

  • Digest objects (like Digest::MD5) as formatted hexdumps, including a mention when, like in the example above, the digest is actually is the one of a reset (empty) element.

There are several different filters available on CPAN and you can make some new ones yourself!

In Short

Data::Printer is a shiny tool for your Perl utility belt that not only pretty-prints variables, but also provides very useful information regarding your data. It is also extremely easy to tweak to suit your own taste and debugging needs, from colors to formatting to new filters.

If you're not using it already, give it a go!

Gravatar Image This article contributed by: Breno G. de Oliveira <garu@cpan.org>