1

リンク内のjavascriptを再帰的に分析するスクリプトがあるので、javascriptが見つかった場合は、javascriptを分析し、分析しているjavascriptにさらにjavascriptが含まれている場合は、続行します。ただし、この再帰が停止しないという問題が発生しました。この再帰のタイムアウトを追加する方法はありますか?

4

4 に答える 4

6

Python には組み込みの再帰制限がありRuntimeError、これを超えると a が発生します。デフォルトでは、スタック制限は 1000 です。

try:
    func_that_may_recurse_infinitely()   # i.e., your JavaScript crawler func
except RuntimeError as e:
    if "recursion" in str(e):
        print "stop all the downloadin'!"

sys.setrecursionlimit()より深くまたはより浅くする必要がある場合は、再帰の初期制限を変更できます。

ただし、より良いアプローチは、set()既に見たアイテムの 1 つを保持し、既に処理したアイテムの処理を単に拒否することです。これにより、そもそも再帰的な状況に陥るのを防ぐことができます。

于 2012-07-17T18:10:11.243 に答える
2

私はkindallに同意する傾向があります。ただし、再帰の深さを制限したい場合は、次のようにすることができます。

def foo(max_depth = 10, cur_depth=0):
    if cur_depth >= max_depth:
        return BASE_CASE

    else:
        return foo(max_depth, cur_depth+1)
于 2012-07-17T18:14:08.677 に答える
2

手っ取り早い解決策は、time.time() を呼び出して比較することです。たとえば、次のような単純な階乗関数があるとします。

def fact(i):
  if i == 0 or i == 1: return 1
  return i * fact(i-1)

fact(-1) を呼び出すと、再帰の深さが最大になるため、しばらくスピンしてから RuntimeError が発生します。

次のようにタイムアウトを追加できます。

import time

def factWithTimeout(i, timeout):
  def fact(i, endtime):
    if time.time() > endtime:
      raise RuntimeError('Timeout')
    if i == 0 or i == 1: return 1
    return i * fact(i-1, endtime)
  return fact(i, time.time() + timeout)

ここで、 を呼び出すとfactWithTimeout(-1, 0.0001)、約 100us だけスピンし、タイムアウトのために RuntimeError で終了します。

明らかに、1 ミリ秒未満で再帰制限に達するほど単純な関数の場合、これはそれほど違いはありませんが、より現実的な関数の場合は問題になりません。

于 2012-07-17T18:20:43.563 に答える
1

次のようなことができます。

import time

start = time.time()
timeout_limit = 30   # 30 seconds, or some other number.

def foo():
    if time.time() > start + timeout_limit:
        return 0

    # insert code here.

    foo()

...そして、グローバル変数が必要ない場合は、これを試すことができます:

class Foo(object):
    def __init__(self, timeout_limit):
        self.timeout_limit = timeout_limit

    def run(self, ...):
        self.start = time.time()
        self._run(...)

    def _run(self, ...):
        if time.time() > self.start + self.timeout_limit:
            return

        # insert code here.

        self._run(...)

...それはやり過ぎかもしれませんが。

于 2012-07-17T18:13:13.630 に答える