WWW::CURL::Multi 模块出现写入错误
我正在尝试与 Perl 的 WWW::Curl::Multi 模块并行下载网络上的一堆文件,但收到以下错误:
Use of uninitialized value in ref-to-glob 位于 AA.pm 第 17 行。
未打开的文件句柄上的 syswrite() AA.pm 第 17 行。
在
中使用未初始化的值 子例程入口位于 AA.pm 第 60 行。
如果有人能找出这些错误的原因,我将不胜感激。
package AA;
use strict;
use warnings;
use WWW::Curl::Easy;
use WWW::Curl::Multi;
use Data::Dumper;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub tofile {
return syswrite($_[1], $_[0]); #This is where first and the second error occurs
}
sub downloadfiles{
my $self = shift;
my $files = shift;
my %easy;
my $curl = WWW::Curl::Easy->new;
my $active_handles = 0;
my $curlm = WWW::Curl::Multi->new;
my $dir = "dl/";
my $fh;
foreach my $file (@$files) {
my $curl_id = $active_handles + 1; # This should be a handle unique id.
my $code = 0;
$easy{$curl_id} = $curl;
$code+= $curl->setopt(CURLOPT_PRIVATE, $curl_id);
#Open the filehandle
open($fh, ">$dir$curl_id") or die "\nopen: $!\n\n";
binmode $fh;
# do the usual configuration on the handle
$code+= $curl->setopt(CURLOPT_FILE, *$fh);
$code+= $curl->setopt(CURLOPT_FAILONERROR, 1);
$code+= $curl->setopt(CURLOPT_HEADER, 1);
$code+= $curl->setopt(CURLOPT_CONNECTTIMEOUT, 2);
$code+= $curl->setopt(CURLOPT_URL, $file);
$code+= $curl->setopt(CURLOPT_WRITEFUNCTION, \&tofile);
$code+= $curl->setopt(CURLOPT_NOPROGRESS, 1);
$code+= $curl->setopt(CURLOPT_VERBOSE, 0);
$code+= $curl->setopt(CURLOPT_HEADER, 0);
if ($code ne 0) {
die("Failed to initialize curl");
}
# Add some easy handles
$curlm->add_handle($curl);
$active_handles++;
}
print "\nActive handles: ".$active_handles."\n";
while ($active_handles) {
my $active_transfers = $curlm->perform; #This is where second error comes from
if ($active_transfers != $active_handles) {
while (my ($id, $return_value) = $curlm->info_read) {
print $id;
if ($id) {
$active_handles--;
my $actual_easy_handle = $easy{$id};
delete $easy{$id};
}
}
}
}
close $fh;
}
1;
I'm trying to download a bunch of files on the web in parallel with the Perl's WWW::Curl::Multi module but I'm receiving the following errors:
Use of uninitialized value in
ref-to-glob cast at AA.pm line 17.syswrite() on unopened filehandle at
AA.pm line 17.Use of uninitialized value in
subroutine entry at AA.pm line 60.
I'll appreciate if someone can figure out why those errors come from.
package AA;
use strict;
use warnings;
use WWW::Curl::Easy;
use WWW::Curl::Multi;
use Data::Dumper;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub tofile {
return syswrite($_[1], $_[0]); #This is where first and the second error occurs
}
sub downloadfiles{
my $self = shift;
my $files = shift;
my %easy;
my $curl = WWW::Curl::Easy->new;
my $active_handles = 0;
my $curlm = WWW::Curl::Multi->new;
my $dir = "dl/";
my $fh;
foreach my $file (@$files) {
my $curl_id = $active_handles + 1; # This should be a handle unique id.
my $code = 0;
$easy{$curl_id} = $curl;
$code+= $curl->setopt(CURLOPT_PRIVATE, $curl_id);
#Open the filehandle
open($fh, ">$dir$curl_id") or die "\nopen: $!\n\n";
binmode $fh;
# do the usual configuration on the handle
$code+= $curl->setopt(CURLOPT_FILE, *$fh);
$code+= $curl->setopt(CURLOPT_FAILONERROR, 1);
$code+= $curl->setopt(CURLOPT_HEADER, 1);
$code+= $curl->setopt(CURLOPT_CONNECTTIMEOUT, 2);
$code+= $curl->setopt(CURLOPT_URL, $file);
$code+= $curl->setopt(CURLOPT_WRITEFUNCTION, \&tofile);
$code+= $curl->setopt(CURLOPT_NOPROGRESS, 1);
$code+= $curl->setopt(CURLOPT_VERBOSE, 0);
$code+= $curl->setopt(CURLOPT_HEADER, 0);
if ($code ne 0) {
die("Failed to initialize curl");
}
# Add some easy handles
$curlm->add_handle($curl);
$active_handles++;
}
print "\nActive handles: ".$active_handles."\n";
while ($active_handles) {
my $active_transfers = $curlm->perform; #This is where second error comes from
if ($active_transfers != $active_handles) {
while (my ($id, $return_value) = $curlm->info_read) {
print $id;
if ($id) {
$active_handles--;
my $actual_easy_handle = $easy{$id};
delete $easy{$id};
}
}
}
}
close $fh;
}
1;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我看到您初始化了一个文件句柄
$fh
来存储下载的数据,但我不知道该值如何传递给您的tofile
函数。你需要说代替吗
?
如果您在
tofile
中添加一行来打印该函数的输入 (@_
),您会看到什么?I see you initialize a filehandle
$fh
to store the downloaded data, but I don't see how that value ever gets passed to yourtofile
function. Do you need to sayinstead of
?
What do you see if you put an extra line in
tofile
that prints out the inputs (@_
) to that function?我意识到问题不在于脚本,而在于我使用的旧 BSD 机器(带有旧版本的 perl)。
您可以使用以下几行测试代码:
但是该脚本在运行后还有另一个错误,它仅将内容输出到最后一个文件。因为我们正在改变 $fh 的值。您可以通过在 for 循环中本地定义 $fh 并将其放入哈希中来修复。退出子程序时关闭
fh 在哈希中。
I've realized that the problem was not about the script, it was rather about the old BSD machine(with the old version of perl) I was using.
You can test the code with the following lines:
But there is another bug in that script after being able to run it, it outputs the contents to only the last file. Because we are changing the values of $fh. You can fix by defining $fh locally in the for loop and put it in a hash. When exiting the subroutine close the
fh's in the hash.