8

Is there any easy way to tell perl "now ignore everything that is printed"?

I have to call a procedure in an external Perl module, but the procedure prints a lot of unnecessary information (all through standard print).

I know select can be used to redirect it somehow, but I am not too wise from reading perldoc on it.

edit: I found the answer sooner, but I will add an example to make it clearer (but not much I guess)

use TectoMT::Scenario;
use TectoMT::Document;

sub tagDocuments {
    my @documents = @_;

    my $scenario = TectoMT::Scenario->new({'blocks'=> [ qw(
            SCzechW_to_SCzechM::Sentence_segmentation 
            SCzechW_to_SCzechM::Tokenize  
            SCzechW_to_SCzechM::TagHajic
            SCzechM_to_SCzechN::Czech_named_ent_SVM_recognizer) ]});

    $scenario->apply_on_tmt_documents(@documents);
    return @documents;
}

TectoMT::Scenario and TectoMT::Document are those external modules

brian d foy
  • 129,424
  • 31
  • 207
  • 592
Karel Bílek
  • 36,467
  • 31
  • 94
  • 149

5 Answers5

13

My own answer:

use IO::Null;

print "does print.";

my $null = IO::Null;
my $oldfh = select($null); 

print "does not print.";

select($oldfh);

print "does print.";
Karel Bílek
  • 36,467
  • 31
  • 94
  • 149
8

I realise that this has been answered, but I think it's worth knowing about an alternative method of doing this. Particularly if something is hell-bent on printing to STDOUT

# Store anything written to STDOUT in a string.
my $str;
open my $fh, '>', \$str;
{
  local *STDOUT = $fh;
  code_that_prints_to_stdout();
}

The key bit is local *STDOUT. It replaces the normal STDOUT with a filehandle of your choosing, but only for the scope of the block containing the local.

Dominic Mitchell
  • 11,861
  • 4
  • 29
  • 30
7

Referring to some answers here and on other threads, I came up with this;

use strict;
use warnings;
use File::Spec;

sub my_functor { system("some_noisy_command.exe", "--option1", "--option2"); }
silently(\&my_functor);

Where "silently()" takes a functor and runs it with stdout redirected:

sub silently($) {
    #Turn off STDOUT
    open my $saveout, ">&STDOUT";
    open STDOUT, '>', File::Spec->devnull();

    #Run passed function
    my $func = $_[0];
    $func->();

    #Restore STDOUT
    open STDOUT, ">&", $saveout;
}
RJFalconer
  • 10,890
  • 5
  • 51
  • 66
2
open my $saveout, ">&STDOUT";
open STDOUT, '>', "/dev/null";

(do your other stuff here)

open STDOUT, ">&", $saveout;
bmb
  • 6,058
  • 2
  • 37
  • 58
  • 2
    problem with this is I want the code to be multiplatform and not all systems have /dev/null. Luckily, there is IO::Null to save me. – Karel Bílek Sep 04 '09 at 00:24
  • You might want to mention that requirement in the question – glenn jackman Sep 04 '09 at 16:27
  • IO:Null does not affect external called programs. but you can use method above for supported system (perl can detect OS), and IO:Null for unsupported. You can cover it by your own function that will automatically select properly method. Notice, not only STDOUT is problem, the same problem is with STDERR, then you should redirect both streams. – Znik Jan 12 '17 at 10:30
1

If you want to use only modules in the standard library, File::Spec has the devnull() function. It returns a string representing the null device ("/dev/null" on *nix) that you can presumably open with open().

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183