Data-Printer icon indicating copy to clipboard operation
Data-Printer copied to clipboard

confusing 'changing output targets' documentation

Open kanliot opened this issue 4 years ago • 4 comments

from https://metacpan.org/pod/Data::Printer

Changing output targets

By default, p() will be set to use STDERR. As of version 0.27, you can set up the 'output' property so Data::Printer outputs to several different places:

output => 'stderr' - Standard error. Same as *STDERR

output => 'stdout' - Standard output. Same as *STDOUT

output => $filename - Appends to filename.

output => $file_handle - Appends to opened handle

output => \$scalar - Appends to that variable's content

appantly this code

use Data::Printer output => $filename 

does not work since $filename is undefined at compile time

Please believe me when I say this was very confusing to me. I don't think the output=>$file_handle works either. I would like an updated example that works, or something like that. Or another way to set the output to a file. I only ask because I don't understand much about the Data::Printer class.

Thanks!

also when writing to a file, the file will not be line-buffered. this means you're probably just better off redirecting stdout, since there is no way to flush the output of p() before you look for output.

kanliot avatar Mar 29 '20 17:03 kanliot

Hello! Thank you for using Data::Printer and for taking the time to file this issue.

You are absolutely right: variables aren't defined at compile time unless placed inside BEGIN blocks. What I meant by $filename is "any string that is neither 'stdout' nor 'stderr'" - though you could of course use a variable too. This should have been clearer on the documentation, and I'll try to make it right on the upcoming releases. Meanwhile, there are many ways to get it working:

  1. hardcoding the filename:
use Data::Printer output => '/path/to/some/file.log';
# (...)
p $data;
  1. requiring Data::Printer at runtime:
# (...)
require DDP; DDP->import( output => $filename );
# (...)
DDP::p($data);
  1. making sure $filename is defined before DDP is loaded:
my $filename;
BEGIN { $filename = '/path/to/some/file.log'; }
BEGIN { use Data::Printer output => $filename; }
# (...)
p $data;
  1. Passing the output parameter on each p() or np() call:
use DDP;
# (...)
p $data, output => $filename;

ou can of course add this to some logging method of your own:

use Data::Printer;
my $filename = '/path/to/some/file.log';
# (...)
logme( $somedata );
# (...)
sub logme ($data) {
  p $data, output => $filename;
}
  1. Putting the filename, hardcoded, on a configuration file (.dataprinter), then have DDP load it automatically.

Finally, while you can autoflush STDOUT with local $| = 1, you're also right that there is no option to flush the contents after each print (I'll look into it). Meanwhile you could pass a handle with flush activated, like:

use IO::Handle;
use Data::Printer;
# (...)
open my $fh, '>>', '/path/to/some/data.log' or die $!;
$fh->autoflush;
# (...)
p $data, output => $fh;

Hope this helps!

garu avatar Mar 30 '20 03:03 garu

wow. Excellent response. All of these would fix the issue.

Thanks!

kanliot avatar Mar 31 '20 17:03 kanliot

Also I can see that logging certain things to some files, and different things to a different logfile is actually a feature I plan to use.

kanliot avatar Mar 31 '20 17:03 kanliot

Can you also permit the use of objects (e.g. Path::Tiny) as an output target? A reference to an object that overloads stringification is also a useful string.

grr avatar Oct 09 '20 00:10 grr