Data :: Dumper :: Freezer正确使用

时间:2015-10-09 13:40:04

标签: perl serialization

我试图在旧的和大型的Perl项目中记录数据结构。为了做到这一点,我使用Data::Dumper,但是,有些结构有点太大并且垃圾邮件日志。所以我正在寻找一种以不那么冗长的方式记录它们的方法。

现在,Dumper的doc提到$Data::Dumper::Freezer = <method_name>变量,可以用来解决这个问题。我尝试过使用它。

添加一个返回&#34;缩短&#34;的序列化方法。虽然该方法被调用,但值不会产生任何结果。使序列化方法对$ _ [0]起作用会产生所需的效果,但会破坏原始数据结构。

我很困惑。我究竟做错了什么?我该如何解决?

这是一个精致的示例代码:

#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Indent = 0;
$\="\n";

my $x = Foo->new ( answer => 42, use => "force" );
my $y = { foo => $x };

print "initial plain:\n\t", Dumper( $x );
print "initial compound:\n\t", Dumper( $y );

{
    local $Data::Dumper::Freezer = 'freeze_pure';
    print "still not abbreviated data:\n\t", Dumper( $y );
};
{
    local $Data::Dumper::Freezer = 'freeze_replace';
    print "abbreviated data:\n\t", Dumper( $y );
};

print "initial data is still intact:\n\t", Dumper( $x );
print "compound data is corrupted:\n\t", Dumper( $y );

package Foo;

sub new {
    my $class = shift;
    return bless { @_ }, $class;
};

sub freeze_pure {
    my $self = $_[0];
    warn "# In freeze_pure";
    return bless { 
        values => join ",", values %$self 
    }, (ref $self) . "::short";
};

sub freeze_replace {
    my $self = $_[0];
    warn "# In freeze_replace";
    $_[0] = bless {
        values => join ",", values %$self 
    }, (ref $self) . "::short";
    return;
};

输出:

initial plain:
    $VAR1 = bless( {'use' => 'force','answer' => 42}, 'Foo' );
initial compound:
    $VAR1 = {'foo' => bless( {'use' => 'force','answer' => 42}, 'Foo' )};
# In freeze_pure at dumper-freezer.pl line 36.
still not abbreviated data:
    $VAR1 = {'foo' => bless( {'use' => 'force','answer' => 42}, 'Foo' )};
# In freeze_replace at dumper-freezer.pl line 42.
abbreviated data:
    $VAR1 = {'foo' => bless( {'values' => 'force,42'}, 'Foo::short' )};
initial data is still intact:
    $VAR1 = bless( {'use' => 'force','answer' => 42}, 'Foo' );
compound data is corrupted:
    $VAR1 = {'foo' => bless( {'values' => 'force,42'}, 'Foo::short' )};

1 个答案:

答案 0 :(得分:4)

虽然文档有点稀疏,但冷冻/烤面包机的预期用途是数据序列化/反序列化,而不是调试输出的预处理。

因此,Data :: Dumper调用freezer方法,但不使用返回值。这个想法可能是因为如果你要对一个对象进行序列化,那么在你对它进行反序列化之前,你不会再次搞乱它,所以更改对象本身没有问题。

以下是Data :: Dumper源中的relevant section of code

# Call the freezer method if it's specified and the object has the
# method.  Trap errors and warn() instead of die()ing, like the XS
# implementation.
my $freezer = $s->{freezer};
if ($freezer and UNIVERSAL::can($val, $freezer)) {
  eval { $val->$freezer() };
  warn "WARNING(Freezer method call failed): $@" if $@;
}

如果您只想减少日志中输出的大小,可以通过将$Data::Dumper::Indent设置为零来删除换行符和缩进:

use Data::Dumper;
use WWW::Mechanize;

$Data::Dumper::Indent = 0;
my $mech = WWW::Mechanize->new;
print Dumper $mech;

输出:

$VAR1 = bless( {'headers' => {},'ssl_opts' => {'verify_hostname' => 1},'forms' => undef,'page_stack' => [],'text' => undef,'requests_redirectable' => ['GET','HEAD','POST'],'timeout' => 180,'onerror' => sub { "DUMMY" },'current_form' => undef,'links' => undef,'max_redirect' => 7,'quiet' => 0,'images' => undef,'noproxy' => 0,'stack_depth' => 8675309,'show_progress' => undef,'protocols_forbidden' => undef,'no_proxy' => [],'handlers' => {'request_prepare' => bless( [{'owner' => 'LWP::UserAgent::cookie_jar','callback' => sub { "DUMMY" },'line' => '/home/foo/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/LWP/UserAgent.pm:705'}], 'HTTP::Config' ),'response_header' => bless( [{'owner' => 'LWP::UserAgent::parse_head','callback' => sub { "DUMMY" },'m_media_type' => 'html','line' => '/home/foo/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/LWP/UserAgent.pm:684'}], 'HTTP::Config' ),'response_done' => bless( [{'owner' => 'LWP::UserAgent::cookie_jar','callback' => sub { "DUMMY" },'line' => '/home/foo/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/LWP/UserAgent.pm:708'}], 'HTTP::Config' )},'onwarn' => sub { "DUMMY" },'protocols_allowed' => undef,'use_eval' => 1,'local_address' => undef,'autocheck' => 1,'title' => undef,'def_headers' => bless( {'user-agent' => 'WWW-Mechanize/1.75'}, 'HTTP::Headers' ),'cookie_jar' => bless( {'COOKIES' => {}}, 'HTTP::Cookies' ),'proxy' => {},'max_size' => undef}, 'WWW::Mechanize' );

这仍然是很多输出,但它肯定比以下更紧凑:

$VAR1 = bless( {
                 'headers' => {},
                 'ssl_opts' => {
                                 'verify_hostname' => 1
                               },
                 'forms' => undef,
                 'page_stack' => [],
                 'text' => undef,
                 'requests_redirectable' => [
                                              'GET',
                                              'HEAD',
                                              'POST'
                                            ],
                 'timeout' => 180,
                 'onerror' => sub { "DUMMY" },
                 'current_form' => undef,
                 'links' => undef,
                 'max_redirect' => 7,
                 'quiet' => 0,
                 'images' => undef,
                 'noproxy' => 0,
                 'stack_depth' => 8675309,
                 'show_progress' => undef,
                 'protocols_forbidden' => undef,
                 'no_proxy' => [],
                 'handlers' => {
                                 'request_prepare' => bless( [
                                                               {
                                                                 'owner' => 'LWP::UserAgent::cookie_jar',
                                                                 'callback' => sub { "DUMMY" },
                                                                 'line' => '/home/foo/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/LWP/UserAgent.pm:705'
                                                               }
                                                             ], 'HTTP::Config' ),
                                 'response_header' => bless( [
                                                               {
                                                                 'owner' => 'LWP::UserAgent::parse_head',
                                                                 'callback' => sub { "DUMMY" },
                                                                 'm_media_type' => 'html',
                                                                 'line' => '/home/foo/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/LWP/UserAgent.pm:684'
                                                               }
                                                             ], 'HTTP::Config' ),
                                 'response_done' => bless( [
                                                             {
                                                               'owner' => 'LWP::UserAgent::cookie_jar',
                                                               'callback' => sub { "DUMMY" },
                                                               'line' => '/home/foo/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/LWP/UserAgent.pm:708'
                                                             }
                                                           ], 'HTTP::Config' )
                               },
                 'onwarn' => sub { "DUMMY" },
                 'protocols_allowed' => undef,
                 'use_eval' => 1,
                 'local_address' => undef,
                 'autocheck' => 1,
                 'title' => undef,
                 'def_headers' => bless( {
                                           'user-agent' => 'WWW-Mechanize/1.75'
                                         }, 'HTTP::Headers' ),
                 'cookie_jar' => bless( {
                                          'COOKIES' => {}
                                        }, 'HTTP::Cookies' ),
                 'proxy' => {},
                 'max_size' => undef
               }, 'WWW::Mechanize' );

或者,您可以尝试Data::Dump,这样您就可以使用Data::Dump::Filtered过滤输出。我更喜欢Data :: Dump到Data :: Dumper,因为我认为它有更明智的默认值(例如输出空格以外的空格的转义序列)。

我还没有使用过滤功能,但是brian d foy用几个例子写了a nice article