2010-08-21 4 views
2

Приложение My Gae извлекает данные JSON с стороннего сайта; с учетом идентификатора, представляющего элемент для загрузки, данные элемента на этом сайте организованы на нескольких страницах, поэтому мой код должен загружать куски данных, страницы за страницей, пока не будут получены данные последней доступной страницы.
Мой упрощен код выглядит следующим образом:Google App Engine: как распараллелить загрузки с помощью TaskQueue или Async Urlfetch?

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}) 

The data_list результатов представляет собой упорядоченный список, где первый элемент имеет данные номер страницы 1 и последний элемент имеет данные последней страницы; этот data_list, после получения, отображается в представлении.

Этот подход работает 99% времени, но иногда из-за предела 30 секунд навязанной Google App Engine, на элементы с большим количеством страниц я получаю страшился DeadlineExceededError. Я хотел бы знать, если использовать TaskQueue | Deferred | AsyncUrlfetch Я мог бы улучшить этот алгоритм, распараллеливая в некотором роде N вызовов URL-адресов.

+0

Позвольте мне знать, если решение ниже работает для вас –

+0

есть вам повезло? –

ответ

1

Используйте это: 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() 
+0

это нормально, где и находится. просто замените раздел while кодом выше и при необходимости измените. не нужны глобальные переменные. –

+1

, хотя и не очень подробный, ваш ответ помог мне сосредоточиться на асинхронном решении. – systempuntoout

0

я решил с этим:

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] 
Смежные вопросы