4

LWP を使用して Web ページからコンテンツをダウンロードしていますが、LWP がページを待機する時間を制限したいと考えています。

my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->env_proxy;
$response = $ua->get("http://XML File");
$content = $response->decoded_content;

問題は、サーバーがときどきデッドロックし (理由を突き止めようとしています)、要求がまったく成功しないことです。サーバーはそれがライブであると認識しているため、ソケット接続を開いたままにしておくため、LWP::UserAgent のタイムアウト値は何の役にも立ちません。リクエストに絶対タイムアウトを強制する最良の方法は何ですか?

タイムアウトが制限に達すると、スクリプトが終了し、スクリプトを続行できなくなります。このスクリプト全体がループに入っており、XML ファイルを順番に取得する必要があります。このタイムアウトを適切に処理し、スクリプトを次のアドレスに継続させたいと思っています。誰もこれを行う方法を知っていますか? ありがとう!!

4

2 に答える 2

8

https://stackoverflow.com/a/10318268/1331451で以前に同様の問題に直面したことがあります。

あなたがする必要があるのは、$SIG{ALRM}ハンドラーを追加し、alarmそれを呼び出すために使用することです。電話をかける前に を設定し、alarmその後すぐにキャンセルします。次に、返された HTTP::Result を見ることができます。

アラームがシグナルをトリガーし、Perl がシグナル ハンドラーを呼び出します。その中で、何かを直接実行しdieたり、単に実行したりできますdie。プログラム全体を壊すことevalはできません。dieシグナル ハンドラが呼び出されると、alarm自動的にリセットされます。

dieハンドラーにさまざまなメッセージを追加し$@、@larsen が彼の回答で述べたように後で区別することもできます。

次に例を示します。

my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new;
my $res;
eval {
  # custom timeout (strace shows EAGAIN)
  # see https://stackoverflow.com/a/10318268/1331451
  local $SIG{ALRM} = sub {
    # This is where it dies
    die "Timeout occured...";
  }; # NB: \n required
  alarm 10;
  $res = $ua->request($req);
  alarm 0;
};
if ($res && $res->is_success) {
  # the result was a success
}
于 2013-04-09T11:08:30.327 に答える
0

一般に、停止evalする可能性のあるコードのセクションをトラップして制御する場合は、ブロックを使用できます。

while( … ) { # this is your main loop
    eval {
        # here the code that can die
    };
    if ($@) {
        # if something goes wrong, the special variable $@ 
        # contains the error message (as a string or as a blessed reference,
        # it depends on how the invoked code threats the exception.
    }
}

eval 関数のドキュメントで詳細情報を見つけることができます

于 2013-04-09T11:09:18.870 に答える