从Perl脚本调用外部程序时,Capture :: Tiny是否在使用system()时避免使用磁盘io?使用任何一种时,我的性能基本相同。一位同事正在使用我的代码并告诉我它正在锤击他的磁盘。我(也许)在我的本地计算机上运行并写入本地磁盘时没有这个问题。
我以前这样做过:
open($fhStdin, ">stdin.txt");
print $fhStdin "some text\n";
close($fhStdin);
system("cmd < stdin.txt 1> stdout.txt 2> stderr.txt");
# open and read stdout.txt
# open and read stderr.txt
改为:
($stdout, $stderr, $exit) = capture {
open($fhStdin, '| cmd');
print $fhStdin "some text\n";
close($fhStdin);
};
但NYTProf告诉我他们运行的时间基本相同(但NYTProf会从子程序时间中删除磁盘io开销)。所以我想知道capture()是否正在写入引擎盖下的临时文件? (我试着阅读Tiny.pm源代码,但我很惭愧地说我无法分辨出来。)
感谢您的任何提示。
答案 0 :(得分:4)
Capture::Tiny::capture的文档说明确实使用了文件
通常对匿名临时文件句柄进行捕获。
这可以在_capture_tee sub的源代码中看到,用作所有方法的通用例程。在这个子程序的大约一半时间内,我们发现call to File::Temp->new
正在发生,除非使用命名文件(见下文)。其余的处理可以小心追踪。†
文档继续提供一种通过命名文件来监视所有这些的方法
要通过命名文件捕获(例如,从外部监视长时间运行的捕获),请提供自定义文件句柄作为选项对的尾随列表:
my $out_fh = IO::File->new("out.txt", "w+"); my $err_fh = IO::File->new("out.txt", "w+"); capture { ... } stdout => $out_fh, stderr => $err_fh;
文件句柄必须是可读/写且可搜索的。在捕获操作期间修改文件或文件句柄将产生不可预测的结果。它们上的现有IO层可能会被捕获更改。
(如果这样做,那么对File::Temp
的调用就没有了,如上所述。参见来源。)
如果此磁盘活动有问题,您可以使用管道open来读取cmd
的输出
(首先将其输入写入文件),或使用qx(反引号)。但是你必须合并或重定向STDERR
并通过更多的箍来检查和处理错误。
另一种选择是使用IPC::Run3。虽然它也uses files它提供了更多的选项,可以利用它们来减少磁盘I / O,或者完全避免磁盘。 (使用文件句柄打开到标量(内存中)调用的想法不起作用,因为这不是真正的文件句柄。‡)
“核”选项是更复杂的IPC::Run,它可以在不使用磁盘的情况下获取输出。
†粗略草图
_capture_tee
的所有方法的“调度”已完成in the beginning,其中unshift
在@_
获取goto &func
之前将capture
标记为1,1,0,0
离开,区分方法。对于$do_stdout
,这是$do_stderr
,在_capture_tee
中设置变量capture
和File::Temp
。然后,这些用于设置%do
hash,其中的密钥为iterated over to set up $stash
。
如果将额外参数传递给$stash
(对于命名文件),则传递$stash->{capture}
is set,否则会分配run3 \@cmd, \my $in, \my $out, \my $err;
个对象。
my @cmd = qw(ls -l .);
open my $fh, '>', \my $cmd_out; # not a real filehandle ...
run3 \@cmd, \undef, $fh; # ... so this won't work
后来passed to _open_std
发生了重定向。
还有很多,但主要与操纵本地化的球和层有关。
‡最常见的调用写入标量
open
但是这会使用文件,如How it works下的文档中所述。
尝试通过写入打开到标量的文件句柄来欺骗它不使用文件
Capture::Tiny
以
中止run3(): Invalid argument redirecting STDOUT at ...
这是因为标量的df[df['Event'].isin(['event1', 'event2', 'event3'])]
没有设置真正的文件句柄。请参阅this post。
如果文件句柄打开到文件,则按预期工作,写入该文件。与import pandas as pd
df = pd.DataFrame([['event1','01:22:52.134'],['event2','03:21:31.123'], ['event1','21:12:52.544'],['event3','23:12:31.216'],['event1','10:22:02.134'],['event2','06:52:48.184'], ['event3','12:52:46.188'], ['event3','06:52:46.184'], ['event1','13:33:46.235'], ['event2','14:35:12.235'], ['event3','14:59:12.177']], columns=["Events",'Time'])
df
的操作相比,这可能会导致更高效的磁盘I / O操作。