2011-06-20 23 views
9

Tôi muốn đóng STDOUT để ngăn mã của tôi xuất ra một hình ảnh cụ thể mà tôi cần để tính toán thêm nhưng không muốn trên trang web của tôi.Làm cách nào để đóng và mở lại STDOUT trong Perl?

Vì vậy, tôi muốn đóng STDOUT, hãy làm những gì tôi phải làm với mã của mình, sau đó mở lại STDOUT để xuất nội dung lên trang web. (Không vào một tập tin)

Những gì tôi cố gắng là:

close STDOUT; 
    # my code here 
    open STDOUT; 

này không hoạt động ...

Cảm ơn

+2

Tại sao bạn không chỉ in những thứ bạn không muốn in? – cjm

+0

Tôi đang sử dụng cgi_png(), inevitably in đồ thị – Italics

+0

Sau đó, sử dụng scalar_png thay thế. Nó trả về hình ảnh mà cgi_png sẽ in (ngoại trừ tiêu đề CGI). – cjm

Trả lời

9

Có một số cách để tiếp cận vấn đề của bạn và nhiều người trong số họ không yêu cầu bạn đóng STDOUT và phát hiện nguy cơ các kênh I/O tiêu chuẩn của chương trình.

Ví dụ: bạn có thể sử dụng lệnh (1-arg) select để chỉ đạo tạm thời đầu ra của các lệnh print.

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; 

Bạn cũng có thể gán lại *STDOUT glob tại thời gian chạy mà không đóng bất kỳ tay cầm nào.

*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; 
1

Để (tái) STDOUT mở hoặc thiết bị lỗi chuẩn như tệp trong bộ nhớ, đóng tệp trước:

close STDOUT; 
    open STDOUT, '>', \$variable or die "Can't open STDOUT: $!"; 

Từ perl doc: http://perldoc.perl.org/functions/open.html Bạn có: sau khi đóng cửa, đừng làm vậy. Mở ở trên cũng sẽ làm việc với jus

open STDOUT; 

chủ đề này trong các nhà sư perl có thể giúp bạn quá: http://www.perlmonks.org/?node_id=635010

2

Đọc documentation for open.

Tìm kiếm "Đây là tập lệnh lưu, chuyển hướng và khôi phục STDOUT và STDERR bằng các phương pháp khác nhau".

Những gì bạn muốn làm không phải là đóng STDOUT, mà chuyển hướng nó đến/dev/null tạm thời.

5

Thật tệ khi đóng STDOUT vì nhiều giả định nó luôn mở. Tốt hơn là chuyển hướng nó đến /dev/null (unix) hoặc nul (Windows).

Nếu bạn muốn chuyển hướng mô tả tập tin,

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

    ... 
} 

Nếu bạn chỉ muốn chuyển hướng STDOUT,

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

    ... 
} 

Nếu bạn chỉ muốn chuyển hướng xử lý đầu ra mặc định,

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

Trong trường hợp không rõ ràng, mọi thứ sẽ tự động được đặt trở lại bình thường ở cuối khối, bất kể khối đó đã thoát ra sao. – ikegami

1

Tôi đã kiểm tra 2 cách:

  1. qua select
  2. qua *OLD_STDOUT = * STDOUT và thấy chúng không thể sử dụng được trong trường hợp thông thường

Lý do là 2 cách tiếp cận này chuyển hướng STDOUT chỉ khi "in" hoặc cái gì khác được sử dụng trong Tập lệnh Perl. Nhưng nếu bạn sử dụng "hệ thống()" gọi điện thoại hoặc gọi số phụ, sản lượng của họ có tiêu chuẩn STDOUT anyway = ((

Quan điểm của tôi xem, thực sự giải pháp là phải:.

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

Tôi đã kiểm tra giải pháp này và nó làm việc cho tôi

2

Bạn có thể thực hiện một cái gì đó để bắt STDOUT như vậy:.

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

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

    $code->(); 

    return $stdout_string; 
} 

và sau đó sử dụng nó như vậy:

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

Bản địa hóa tệp bên trong stdout_of() cho phép bạn tránh các thủ thuật đóng và mở lại STDOUT.

Các vấn đề liên quan