【问题标题】:Can't use an undefined value as a filehandle reference不能使用未定义的值作为文件句柄引用
【发布时间】:2017-02-09 23:03:59
【问题描述】:

首先我搜索了论坛并没有找到我的问题。 我正在运行安装了 perl 5.10 的 Ubuntu。

我在执行脚本后收到以下错误:

 "Can't use an undefined value as filehandle reference at scraper.pl line 17"

这是我的脚本....

#!/usr/bin/perl -W
use strict;
use warnings;

use WWW::Curl::Easy;


my $curl = WWW::Curl::Easy->new;

$curl->setopt(CURLOPT_HEADER, 1);
$curl->setopt(CURLOPT_URL, 'http://something.com');


my $response_body;
$curl->setopt(CURLOPT_WRITEDATA,\$response_body);

my $return_code = $curl->perform;

if ($return_code == 0)
{
  my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
  print ("Success ".$response_code);
}
else
{
  # Error Code
  print ("An error occured: ".$return_code." ".$curl->strerror($return_code)." ".$curl->errbuf."\n");
}

# EOF

我们将不胜感激。

谢谢,

【问题讨论】:

  • 您在哪里收到错误消息?
  • @Kevin 在 scraper.pl 第 15 行。;)
  • 对不起...错误发生在第 15 行... my $return_code = $curl->perform;
  • 顺便说一句...我使用的代码逐字逐句来自search.cpan.org/~szbalint/WWW-Curl-4.15/lib/WWW/Curl.pm
  • 使用Carp::Always 运行并获取错误的完整堆栈跟踪。 (perl -MCarp::Always the_script.pl)

标签: perl libcurl


【解决方案1】:

代替:

my $response_body;
$curl->setopt(CURLOPT_WRITEDATA,\$response_body);

做:

my $response_body = '';
open(my $fileb, ">", \$response_body);
$curl->setopt(CURLOPT_WRITEDATA,$fileb);

如果你查看你实际安装的 WWW-Curl 版本的文档,我想你会看到它传递的是一个文件句柄,而不是一个标量引用。

或者,升级 WWW-Curl。

另请注意,通常不建议使用 -W;通常模块会禁用特定范围的警告,而大写的 W 开关会阻止这种情况。使用 -w 代替(或者只是 use warnings; 用于您自己的代码,您已经在这样做了)。

【讨论】:

  • 只是问......为什么社区选择支持这个关于解决方案的评论,而我指定解决问题的评论仍然不受欢迎?
  • @Bnjmn:猜猜看,因为另一个人向您提供了一种解决方法,您阅读了错误的文档而不是解释您这样做了?
  • 另外,使用 curl 将某些内容放入临时文件有点奇怪。
  • 感谢您的澄清。我同意使用临时文件并不理想,因为 wget 会是一种更直接的方法。我会相应地调整我认可的解决方案。
【解决方案2】:
#!/usr/bin/perl
使用严格;
使用警告;

使用 WWW::Curl::Easy;
使用 File::Temp qw/tempfile/;

我的 $response_body = tempfile();

我的 $curl = WWW::Curl::Easy->new;

$curl->setopt(CURLOPT_HEADER, 1);
$curl->setopt(CURLOPT_URL, 'http://yiddele.com/categoryindex.aspx');

#$curl->setopt(CURLOPT_WRITEDATA,\$response_body);
$curl->setopt(CURLOPT_WRITEDATA, \$response_body);

我的 $return_code = $curl-> 执行;

如果 ($return_code == 0)
{
  我的 $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
  print("成功".$response_code);
}
别的
{
  # 错误代码
  print ("发生错误:".$return_code." ".$curl->strerror($return_code)." ".$curl->errbuf."\n");
}

#EOF

输出是:

成功200

【讨论】:

  • 谢谢 d5e5,您已经解决了这个问题。非常感谢您的帮助。
  • 这篇文章已被降级为建议的解决方案,因为它代表了一种有点尴尬的解决方法,但它仍然提供了预期的结果,因此我投了赞成票。
  • 谢谢 Bnjmn。在我发布上述内容后,我看到 ysth 在 4 分钟前发布了一个答案,我投了赞成票,因为它包含了解释。此外,我还没有看到与 WWW::Curl::Easy 一起安装的 Curl.pm 文件,它比包含 Easy.pm 的 Curl 文件夹更上一层。它包含使用各种方法的示例,包括执行。
【解决方案3】:

有错误代码:

print ("Success ".$response_code);

查看print 的文档:由于使用括号时解析参数的方式,第一个参数将被解释为文件句柄,这不是你想要的。在您的代码中,括号是不必要的;只需传递一个串联的字符串,或者更好的是,避免串联并传递一个字符串列表:

print 'Success ', $response_code;

另外,请始终在您编写的每个脚本的顶部包含use strict; use warnings;。您会发现许多错误会被突出显示,否则这些错误可能会隐藏很长一段时间,并且当您在 Stack Overflow 上询问之前发现错误时,它还可以节省每个人的时间。 :)

【讨论】:

  • 感谢您的意见...一个真正的业余错误:(
  • @Bnjmn:如果该行永远不会被执行,则不会::p
  • @David - 如您所见,社区在问题发生之前解决了问题;)
  • 我同意print 'Success', $response_code; 是更好的形式的观点,但是parens 真的会导致错误吗?一个简单的perl -We 'my $val = "bar\n"; print ("foo ".$bar);' 在 Cygwin 上对我来说很好。
  • 所以我讨厌痛苦,但我按照以太的建议进行了更改,不幸的是仍然收到相同的错误:(
【解决方案4】:
my $response_body;
$curl->setopt(CURLOPT_WRITEDATA,\$response_body);

您已声明 $response_body,但尚未为其赋值。我认为如果您将其设为字符串,这将起作用。

my $response_body = "";

也就是说,我不能确定,因为我无法重现该错误。或许安装更新版本的模块也会有所帮助。

【讨论】:

  • 感谢您的回复,我知道 perl 在变量初始化方面特别慷慨,因此您提出的修复并没有解决问题。我还下载了最新版本的 Curl 模块,并确保我的 perl 解释器也是最新版本,因为论坛上的先前帖子报告了旧版本 perl 的问题。快速更新,当我将 $response_body 更改为空字符串时,解释器错误会更改并显示“Bad filehandle: at scraper.pl line 15”
  • 从该评论中,$curl->setopt 是否可能期望文件句柄作为其第二个参数,而不是对标量的引用?如果你不介意,试试这个:open my $fh, '>', \$response_body or die "$!"; $curl->setopt(CURLOPT_WRITEDATA, $fh);编辑:文档暗示这无关紧要。
  • @Hugmeir:但他正在检查最新的文档,而不是他拥有的版本的文档。 4.11 至少需要一个文件句柄,而不是一个标量引用。
【解决方案5】:
        use Data::Printer ;
        use URI::Encode qw(uri_encode uri_decode);
        use JSON ();
        use JSON::Parse ':all' ;
        use WWW::Curl;
        use HTTP::Response ;

        use utf8 ;
        use Carp ;
        use Cwd qw ( abs_path ) ;
        use Getopt::Long;

         use WWW::Curl::Easy;

         my $curl = WWW::Curl::Easy->new;
         $curl->setopt(WWW::Curl::Easy::CURLOPT_HEADER(),1);
         $curl->setopt(WWW::Curl::Easy::CURLOPT_URL(), 'https://www.pivotaltracker.com/services/v5/me?fields=%3Adefault');
         $curl->setopt(WWW::Curl::Easy::CURLOPT_HTTPHEADER() , ['X-TrackerToken: ' . $TOKEN]  );
         #$curl->setopt(WWW::Curl::Easy::CURLOPT_POST(), 1);

         # A filehandle, reference to a scalar or reference to a typeglob can be used here.
         my $response_body;
         $curl->setopt(WWW::Curl::Easy::CURLOPT_WRITEDATA(),\$response_body);

         # Starts the actual request
         my $ret = $curl->perform;


         if ($ret == 0) {

              print("Transfer went ok\n");
              my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
              # judge result and next action based on $response_code

              $response_body = HTTP::Response->parse($response_body);
              print("Received response: $response_body\n");
              p($response_body);
              my $json_data = $response_body->content ;

              $json_data = JSON->new->utf8->decode($json_data);
              p($json_data);

         } else {
             # Error code, type of error, error message
              print("An error happened: $ret ".$curl->strerror($ret)." ".$curl->errbuf."\n");
         }

        # my $cmd='curl -X GET -H "X-TrackerToken: ' . "$TOKEN" . '" "https://www.pivotaltracker.com/services/v5/me?fields=%3Adefault"' ;
        # my $json_str = `$cmd`;
        # p($json_str);
        # my $json_data = JSON->new->utf8->decode($json_str);
        # p($json_data);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多