2011-06-20 9 views
9

Chciałbym zamknąć STDOUT, aby mój kod nie generował obrazu potrzebnego do dalszych obliczeń, ale nie chcę na mojej stronie internetowej.Jak zamknąć i ponownie otworzyć STDOUT w Perlu?

Więc chcę zamknąć STDOUT, zrób to, co mam zrobić z moim kodem, a następnie ponownie otwórz STDOUT, aby wyprowadzić rzeczy na stronę internetową. (nie do pliku)

Co próbowałem to:

close STDOUT; 
    # my code here 
    open STDOUT; 

to nie działa ...

Dzięki

+2

Dlaczego nie unikniesz drukowania rzeczy, których nie chcesz drukować? – cjm

+0

Używam cgi_png(), które nieuchronnie wypisuje wykres – Italics

+0

Następnie użyj scalar_png zamiast tego. Zwraca obraz, który wydrukowałby cgi_png (z wyjątkiem nagłówka CGI). – cjm

Odpowiedz

9

Istnieje kilka sposobów podejścia do problemu, a wiele z nich nie wymaga zamykania STDOUT i ryzyka podważania standardowych kanałów we/wy programu.

Na przykład można użyć polecenia (1-arg) select, aby tymczasowo sterować wyjściami poleceń print gdzie indziej.

print $stuff_you_want_to_send_to_STDOUT; 

select(NOT_STDOUT); 
# now default print sends things to NOT_STDOUT. 
# This doesn't need to be a real filehandle, though you may get warning 
# messages if it is not. 
...; 
print $the_image_you_dont_want_to_go_to_STDOUT; 
...; 

select(STDOUT); 
# now print sends things to STDOUT agin 
print $more_stuff_you_do_want_to_go_to_STDOUT; 

Można również przypisanie glob w czasie wykonywania *STDOUT bez zamykania żadnych uchwytów.

*OLD_STDOUT = *STDOUT; 
print $for_STDOUT; 

*STDOUT = *NOT_STDOUT;  # again, doesn't need to be a real filehandle 
print $stuff_to_suppress; 

*STDOUT = *OLD_STDOUT;  # restore original STDOUT 
print $more_stuff_for_STDOUT; 
2

Przeczytaj documentation for open.

Wyszukaj "Oto skrypt, który zapisuje, przekierowuje i przywraca STDOUT i STDERR przy użyciu różnych metod".

Co chcesz zrobić, to nie zamykać STDOUT, ale raczej tymczasowo przekierować go do/dev/null.

5

To źle zamknąć STDOUT, ponieważ wiele zakłada, że ​​jest zawsze otwarty. Lepiej przekieruj go na numer /dev/null (unix) lub nul (Windows).

Jeśli chcesz przekierować deskryptor pliku,

use Sub::ScopeFinalizer qw(scope_finalizer); 

{ 
    open(my $backup_fh, '>&', \*STDOUT) or die $!; 
    my $guard = scope_finalizer { open(STDOUT, '>&', $backup_fh) or die $!; }; 
    open(STDOUT, '>', '/dev/null') or die $!; 

    ... 
} 

Jeśli chcesz po prostu przekierować standardowe wyjście,

{ 
    local *STDOUT; 
    open(STDOUT, '>', '/dev/null') or die $!; 

    ... 
} 

Jeśli chcesz po prostu przekierować uchwyt domyślne wyjście,

use Sub::ScopeFinalizer qw(scope_finalizer); 

{ 
    open(my $null_fh, '>', '/dev/null') or die $!; 
    my $backup_fh = select($null_fh); 
    my $guard = scope_finalizer { select($backup_fh); }; 

    ... 
} 
+1

W przypadku, gdy nie jest jasne, wszystko jest automatycznie przywracane do normalnego na końcu bloku, bez względu na to, jak blok zostanie opuszczony. – ikegami

1

Sprawdziłem 2 sposoby:

  1. poprzez select
  2. poprzez *OLD_STDOUT = * STDOUT i zobaczyć, że nie są używane w przypadku wspólnego.

Powód jest taki, że 2 podejścia przekierowują STDOUT tylko, jeśli "drukuj" lub coś innego jest używane w skrypcie Perla. Ale jeśli używasz „system()” zadzwoń lub zadzwoń indeks, ich wyjście dostał do standardowego STDOUT anyway = ((

Mój punkt widzenia, rzeczywiście rozwiązanie ma być.

#!/usr/bin/perl -w 
my $file1 = "/tmp/out.txt"; 
my $file2 = "/tmp/err.txt"; 
open my $oldSTDOUT, ">&STDOUT"; 
open OLDERR, ">&",\*STDERR; 
open(STDOUT, ">$file1") or print("Can't redirect stdout: to $file1 "); 
open(STDERR, ">$file2") or print("Can't redirect stderr: to $file2 "); 
print "THIS OUTPUT ISN'T GOT TO STANDARD OUTPUT\n"; 
system("pwd"); # this output isn;t got to standard output too, that is right! 
close(STDOUT); 
close(STDERR); 
open STDOUT, ">>&", $oldSTDOUT; 
open STDERR, ">>&OLDERR"; 
print "BUT THIS OUTPUT IS SEEN IN A STANDARD OUTPUT\n"; 

Sprawdziłem to rozwiązanie i pracował dla mnie

2

można zaimplementować coś złapać STDOUT tak:.

sub stdout_of (&) { 
    my $code = shift; 

    local *STDOUT; 
    open STDOUT, '>', \(my $stdout_string = '') 
     or die "reopen STDOUT: $!"; 

    $code->(); 

    return $stdout_string; 
} 

a następnie używać go tak:

my $stdout = stdout_of { print "hello world" }; 

Lokalizacja uchwytu pliku wewnątrz stdout_of() pozwala uniknąć trików zamknięcia i ponownego otwarcia STDOUT.

Powiązane problemy