Google App Engine:TaskQueueまたはAsync Urlfetchを使用してダウンロードを並列化する方法は?

StackOverflow https://stackoverflow.com/questions/3539240

質問

私のGAEアプリケーションは、サードパーティのサイトからJSONデータを取得します。ダウンロードするアイテムを表すIDを考えると、このサイト上のアイテムのデータは複数のページに整理されているため、最後の使用可能なページのデータが取得されるまで、コードはページの後にデータのチャンクをダウンロードする必要があります。
私の簡略化されたコードは次のようになります:

class FetchData(webapp.RequestHandler):
  def get(self):
    ...
    data_list = []
    page = 1
    while True:
      fetched_data= urlfetch.fetch('http://www.foo.com/getdata?id=xxx&result=JSON&page=%s' % page)
      data_chunk = fetched_data["data"] 
      data_list = data_list + data_chunk
      if len(data_list) == int(fetched_data["total_pages"]):
         break
      else:
         page = page +1 
    ...  
    doRender('dataview.htm',{'data_list':data_list} )

data_list 結果は、最初のアイテムにページ番号1のデータがあり、最後のアイテムに最新のページのデータがある順序付けられたリストです。これ data_list, 、一度回収されると、ビューでレンダリングされます。

このアプローチは99%の回数ですが、時には、 30秒 Google App Engineによって課される制限、多くのページのあるアイテムで私は恐ろしいものを得る DeadlineExceededError。使用しているかどうか知りたいです Taskqueue|延期|asyncurlfetch このアルゴリズムは、何らかの方法でnurlfetch呼び出しを並列化することができました。

役に立ちましたか?

解決

これを使って: http://code.google.com/appengine/docs/python/urlfetch/asynchronousrequests.html

これはそうするようなものです:

def handle_result(rpc):
    result = rpc.get_result()
    # ... Do something with result...

# Use a helper function to define the scope of the callback.
def create_callback(rpc):
    return lambda: handle_result(rpc)

rpcs = []
for url in urls:
    rpc = urlfetch.create_rpc()
    rpc.callback = create_callback(rpc)
    urlfetch.make_fetch_call(rpc, url)
    rpcs.append(rpc)

# ...

# Finish all RPCs, and let callbacks process the results.
for rpc in rpcs:
    rpc.wait()

他のヒント

私はこれで解決しました:

chunks_dict = {}

def handle_result(rpc, page):
    result = rpc.get_result()
    chunks_dict[page] = result["data"]

def create_callback(rpc, page):
    return lambda: handle_result(rpc, page)

rpcs = []
while True:
    rpc = urlfetch.create_rpc(deadline = 10)
    rpc.callback = create_callback(rpc, page)
    urlfetch.make_fetch_call(rpc, 'http://www.foo.com/getdata?id=xxx&result=JSON&page=%s' % page)
    rpcs.append(rpc)
    if page > total_pages:
       break
    else:
       page = page +1   
for rpc in rpcs:
    rpc.wait()

page_keys = chunks_dict.keys()
page_keys.sort()
for key in page_keys:
    data_list= data_list + chunks_dict[key]
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top