2016-02-29 44 views
2

這種奇怪的興趣來自於擴展需求,沒有時間去改變設計(重構)。這當然不是好設計,但我現在需要處理它,希望稍後重構。設置一個文件句柄,以便打印到它被安靜地跳過?

早期打開幾個日誌文件,打印到整個代碼。新的要求意味着使用(新)命令行選項(--noflag),這些日誌文件之一是不相關的。

我只能在此刻做的是墊的定義(open my $fh, ...)和所有使用它(print $fh ...與​​。這顯然是不好的設計,它很容易出錯(這也不是很好)。

有沒有辦法做$fh東西時,它與文件相關 使任何下列print $fh ...由intepreter接受,但會導致根本無法運行print,沒有錯誤? (讓我想象一下,比如說$fh = VOID if $flag;。)或者,有沒有一些NULL流或類似的東西?我所知道的全部是STDOUT(1),STDERR(2)和STDIN(0)。

我不想讓$fh在其他地方打印,理想情況下甚至不需要/dev/null(如果可以的話)。我環顧四周,找不到任何相關的東西。如果事實上它已經在那裏,我會很高興指出信息。 任何想法表示讚賞。

PS。有人問過第一個問題(經過多年的使用),請告訴我它是否關閉。


UPDATE

感謝響應。他們提示我添加/改進此問題:是否打印標記爲/dev/null可能已優化,以便「打印」實際上不會發生? (雖然我仍然對是否可以設置一個文件句柄來告訴Perl'不要在這裏打印'感興趣。)

我試圖避免在沒有添加條件的情況下運行void(print)語句。


更新/澄清

總結從註釋位(謝謝!):這不是對性能優化的追求。我完全同意在評論中所說的一切。只是執行毫無意義的陳述(通常大約一百萬)使我感到不安。另外,我對Perl沒有遇到的一些可能的黑暗角落感到好奇。如果你是在UNIX操作系統,你可以使用「的/ dev/null的」

open my $fh, '>', '/dev/null' or die 'This should never happen'; 

開發空會默默接受所有輸入上(這其中大部分已在答覆/意見得到解決。)

+2

爲什麼是/ dev/null的不夠好?印刷本身的執行成本太高了嗎?然後你需要在你的代碼中添加一個條件。目標文件句柄不能阻止打印的發生(儘管你可能會重新定義打印效果......) – Thilo

+0

@Thilo好吧。執行成本不會受到影響。但原則上我寧願不執行無效聲明。另外,我真的很好奇,是否可以設置一個文件句柄來告訴Perl'這裏不打印'。 – zdim

+2

@zdim:如果'/ dev/null'是*「足夠好」*和*「執行成本不會受到影響」*那麼你有你的答案。如果你創建一個臨時黑客來完成工作,那麼你無法真正負擔執行*「無效聲明」*的挑剔。打開文件句柄到'/ dev/null'。這與 – Borodin

回答

1

通過魔法,你可以創建一個神奇的手柄,其操作總是成功的。

perl -e' 
    { 
     package Handle::Dummy; 
     use Tie::Handle qw(); 
     use Symbol qw(gensym); 
     our @ISA = qw(Tie::Handle); 
     sub new { my $fh = gensym; tie *$fh, $_[0]; $fh } 
     sub TIEHANDLE { bless(\my $dummy, $_[0]) } 
     sub READ { return 1; } 
     sub WRITE { return 1; } 
     sub CLOSE { return 1; } 
    } 

    my $fh = Handle::Dummy->new(); 
    print($fh "abc\n") or die $!; 
    close($fh) or die $!; 
    print("ok\n"); 
' 
ok 

這樣可以避免系統調用,但它會用昂貴的Perl子程序調用來代替它們。

它更簡單,更可靠[1]只需使用/dev/null。它可能也會更快。


被標記去/dev/null可能優化

號Perl不知道什麼/dev/null打印。

您認爲系統調用的速度有多慢?這聽起來不像是正確的優化!


  1. 神奇的文件句柄不與系統文件句柄相關聯,因此它不能被傳遞到C庫,這將無法生存exec
+0

如果這是唯一的方法,這非常有效。這完全不是關於優化的問題,如果在這一點上問題不清楚,那麼很抱歉。我喜歡系統調用:)。只是想避免幾百萬次執行無意義的陳述。 (日誌很大。)它很醜。我認爲可能有辦法告訴Perl'這裏沒有打印。'看來這是不可能的。然後它將是'/ dev/null'。謝謝。這是一塊神奇的:)。 – zdim

3

+0

好的,謝謝。如果可能,我寧願不打印。在我的理解中,打印到'/ dev/null'仍然會去,如果可能的話,我寧願不打印所有那些打印件。但這是次佳。 – zdim

+4

@zdim:不要考慮它。除非你已經對你的代碼進行了簡介,並優化了最嚴重的瓶頸,否則你可能不知道有更嚴重的暴行。這只是不成熟的優化 – Borodin

-1

您可以使用an anonymous, temporary file(大約是perldoc頁面四分之一處)像這樣;

#!/usr/bin/env perl 
use strict; 
use Getopt::Long; 

my $fh; 
my $need_log = 2; 
print "Intitial need_log: $need_log\n"; 

GetOptions('flag!' => \$need_log); 
print "After option processing, need_log: ", $need_log, "\n"; 

if ($need_log) { 
    open($fh, '>', "log.txt") or die "Failed to open log: $!\n"; 
} 
else { 
    open($fh, '>', undef); 
} 

print $fh "Hello World... NOT\n"; 
exit 0; 

下面是不同的使用--flag選項的幾個運行;

[email protected]:~$ ls -l log.txt 
ls: cannot access log.txt: No such file or directory 
[email protected]:~$ ./nf.pl 
Intitial need_log: 2 
After option processing, need_log: 2 
[email protected]:~$ cat log.txt 
Hello World... NOT 
[email protected]:~$ rm log.txt 
[email protected]:~$ 
[email protected]:~$ 
[email protected]:~$ ./nf.pl --flag 
Intitial need_log: 2 
After option processing, need_log: 1 
[email protected]:~$ cat log.txt 
Hello World... NOT 
[email protected]:~$ rm log.txt 
[email protected]:~$ 
[email protected]:~$ 
[email protected]:~$ ./nf.pl --noflag 
Intitial need_log: 2 
After option processing, need_log: 0 
[email protected]:~$ cat log.txt 
cat: log.txt: No such file or directory 
[email protected]:~$ 

我初始化$need_log變量「2」這樣我們就可以知道它有一個「真」值作爲flag選項存在的結果(在這種情況下,它會具有值),或者根本沒有提及標誌選項(在這種情況下,它將具有值)。

指定「--noflag」觸發其具有「民主基金」作爲創建匿名臨時文件中的第三個參數的其他條款。這並不完全符合你完全不寫的問題,但如果文件是臨時的,並且你沒有在其中放入千兆字節,這就足夠了。

+1

這是錯誤方向的一步,因爲它不僅涉及操作系統,而且還寫入磁盤。 – ikegami

+0

像這樣的匿名臨時文件對於系統管理員來說是一件痛苦的事情,因爲他們可以佔用所有磁盤空間,並且無法看到發生這種情況。 –

+0

1)OP從未聲明過不會涉及操作系統 – Marty

2

閉幕你的文件句柄

close $fh; 

會使你所有的prints到那個文件句柄失敗。運行

no warnings 'closed'; 

壓制所有的警告信息,將產生(你做use warnings,對吧?)

+0

好的,這很有趣:)。我會'使用警告;'這樣放下它們就算是別的東西了。嚴重:有很多其他I/O正在運行,所以這可能是危險的 - 它會在全局範圍內禁用它,對於所有內容,對不對?好主意,但沒有想到這一點。 – zdim

相關問題