2011-06-20 17 views
9

Me gustaría cerrar STDOUT para evitar que mi código muestre una imagen particular que necesito para un mayor cálculo pero que no quiero en mi página web.¿Cómo se puede cerrar y volver a abrir STDOUT en Perl?

Así que quiero cerrar STDOUT, hacer lo que tengo que hacer con mi código, y luego volver a abrir STDOUT para imprimir cosas en una página web. (no a un archivo)

Lo que intenté es:

close STDOUT; 
    # my code here 
    open STDOUT; 

Esto no funciona ...

Gracias

+2

¿Por qué no solo evita imprimir cosas que no quiere imprimir? – cjm

+0

Estoy usando cgi_png() que inevitablemente imprime el gráfico – Italics

+0

Luego use escalar_png en su lugar. Devuelve la imagen que imprimiría cgi_png (excepto el encabezado CGI). – cjm

Respuesta

9

Existen varias formas de abordar su problema, y ​​muchas de ellas no requieren que cierre STDOUT y corra el riesgo de dañar los canales de E/S estándar de su programa.

Por ejemplo, puede usar el comando (1-arg) select para dirigir la salida de los comandos print en otro lugar temporalmente.

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; 

También puede reasignar el pegote *STDOUT en tiempo de ejecución sin cerrar ningún asas.

*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

Leer el documentation for open.

Buscar "Aquí hay una secuencia de comandos que guarda, redirige y restaura STDOUT y STDERR utilizando varios métodos".

Lo que quiere hacer no es cerrar STDOUT, sino redirigirlo a/dev/null temporalmente.

5

Es malo cerrar STDOUT ya que se asume que siempre está abierto. Es mejor redirigirlo a /dev/null (unix) o nul (Windows).

Si desea redirigir el descriptor de archivo,

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 $!; 

    ... 
} 

Si lo que desea es redirigir la salida estándar,

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

    ... 
} 

Si lo que desea es redirigir la manija de salida predeterminada,

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

En caso de que no esté claro, todo vuelve automáticamente a la normalidad al final del bloque, sin importar cómo se salga del bloque. – ikegami

1

Comprobé 2 formas:

  1. través select
  2. través *OLD_STDOUT = * STDOUT, y ver que no son utilizables en caso común.

La razón es que estos 2 enfoques redirigen a STDOUT solo si se usa "print" u otra cosa en una secuencia de comandos Perl. Pero si se utiliza "sistema()" llamada o llamada de subíndice, su producción llegó a norma STDOUT todos modos = ((

Mi punto de vista, el hecho solución es ser:.

#!/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"; 

Revisé esta solución y que trabajó para mí

2

se puede implementar algo para coger la salida estándar de este modo:.

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

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

    $code->(); 

    return $stdout_string; 
} 

y luego usarlo de esta manera:

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

La localización del identificador de archivo dentro de stdout_of() le permite evitar los trucos de cerrar y volver a abrir STDOUT.

Cuestiones relacionadas