2016-02-29 21 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

相关问题