现在出现了新的需求:必须向库添加日志记录。这必须自动且透明地完成,而不需要标准库的用户更改其脚本。可以简单地向通用库方法添加日志记录调用;这是易事。困难之处在于这些脚本的诊断输出总是使用“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很烂”或“此示例有缺陷xyz”等问题……这是为了简洁和清晰而大大简化的。
基本问题归结为捕获和处理传递给print(或任何perl内置函数,沿着这些推理线路)的数据。 可以吗? 有没有干净的方法? 是否有任何记录模块具有钩子来让您执行它? 还是需要像瘟疫一样避免它,而且我应该放弃捕获和处理打印输出的想法?
额外信息:必须在跨平台上运行-无论是windows还是*nix。 脚本的运行过程必须保持不变,脚本的输出也必须如此。
额外额外信息:codelogic答案的评论中提出了一个有趣的建议:
您可以对http://perldoc.perl.org/IO/Handle.html进行子类化并创建自己的文件句柄,该文件句柄将执行日志记录工作。 - Kamil Kisiel
这可能会做到这一点,但有两个警告:
1)我需要一种方式将此功能导出给使用公共库的任何人。 它必须自动适用于STDOUT,可能还有STDERR。
2) IO::Handle文档说你不能对其进行子类化,而我的尝试迄今为止都没有成功。是否需要特殊处理才能使子类化IO::Handle工作?标准的'use base'然后覆盖new/print方法似乎没有任何作用。
最终编辑:看起来IO::Handle是个死胡同,但Tie::Handle可能可行。感谢所有建议;它们都非常好。我将尝试Tie::Handle路线。如果它引起问题,我会回来的!
补充说明:请注意,在与此有关的工作中,我发现如果不做任何花哨的事情,Tie::Handle可以使用。如果您在绑定的STDOUT或STDERR上使用IO::Handle的任何功能,则基本上是随机的,无法可靠地使它们正常工作-我找不到一种方法来使IO::Handle的autoflush方法在我的绑定句柄上工作。如果在绑定句柄之前启用了autoflush,则可以正常工作。如果这适用于您,那么Tie::Handle路线可能是可接受的。