现在已经到了新的需求:现在必须将日志记录添加到库中。这必须自动而透明地进行,没有标准库的用户需要更改其脚本。通用库方法可以简单地添加日志调用;这是很容易的部分。困难的部分在于,这些脚本的诊断输出始终使用’print’语句显示。必须存储此诊断输出,但同样重要的是进行处理。
作为这个处理的一个例子,库应该只记录包含单词“warning”,“error”,“notice”或“attention”的打印行。以下极其简单和有争议的示例代码(tm)将记录一些所述输出:
sub CheckPrintOutput { my @output = @_; # args passed to print eventually find their way here. foreach my $value (@output) { Log->log($value) if $value =~ /warning|error|notice|attention/i; } }
(我想避免这样的问题,应该实际记录什么,打印不应该用于诊断,“perl吸”,或者“这个例子有缺点xy和z”…这是大大简化为了简洁和清晰。)
基本的问题在于捕获和处理传递给打印的数据(或按照这些推理方式,任何perl内置的)。可能吗?有没有办法干净地做?有没有任何记录模块有钩可以让你这样做?还是应该像瘟疫那样避免这样的事情,我应该放弃永远捕捉和处理打印输出?
附加:这必须运行跨平台的Windows和* nix。运行脚本的过程必须保持不变,与脚本的输出一样。
附加补充:在codelogic答案的评论中提出了一个有趣的建议:
You can subclass 07000 and create your
own file handle which will do the logging work. – Kamil Kisiel
这可能有两个注意事项:
1)我需要一种将此功能导出到使用公共库的任何人的方法。它必须自动应用于STDOUT,也可能是STDERR。
2)the IO::Handle文件说你不能对它进行子类化,到目前为止我的尝试是无效的。有什么特别需要使子类化IO :: Handle工作吗?标准的’use base’IO :: Handle’然后覆盖新的/打印方法似乎什么都不做。
最终编辑:看起来像IO :: Handle是一个死胡同,但Tie :: Handle可能会这样做。感谢所有的建议;他们都很好我要试穿Tie :: Handle路线。如果造成问题,我会回来的!
附录:注意,在使用这一点后,我发现Tie :: Handle将会工作,如果你不做任何棘手的事情。如果您使用绑定的STDOUT或STDERR的IO :: Handle的任何功能,它基本上是使其工作可靠的难题 – 我找不到一种方法来获取IO :: Handle的自动冲洗方法来处理我的绑定处理。如果我在绑定手柄之前启用了自动冲洗,它将会工作。如果这适用于您,Tie :: Handle路线可能是可以接受的。
解决方法
但是,你可以
>创建一个包
>绑一个手柄
>选择此句柄。
现在有几个人给了基本的框架,但它的工作原理就是这样的:
package IO::Override; use base qw<Tie::Handle>; use Symbol qw<geniosym>; sub TIEHANDLE { return bless geniosym,__PACKAGE__ } sub PRINT { shift; # You can do pretty much anything you want here. # And it's printing to what was STDOUT at the start. # print $OLD_STDOUT join( '','NOTICE: ',@_ ); } tie *PRINTOUT,'IO::Override'; our $OLD_STDOUT = select( *PRINTOUT );
您可以以相同的方式覆盖printf:
sub PRINTF { shift; # You can do pretty much anything you want here. # And it's printing to what was STDOUT at the start. # my $format = shift; print $OLD_STDOUT join( '',sprintf( $format,@_ )); }
请参阅Tie::Handle您可以覆盖STDOUT的行为。