2017-04-24 1 views
0

Ich habe eine AWS Lambda-Funktion, die eine Reihe von URLs unter Verwendung pool.map aufruft. Das Problem ist, dass, wenn eine der URLs irgendetwas anderes als 200 zurückgibt, die Lambda-Funktion fehlschlägt und sofort erneut versucht. Das Problem ist, dass es sofort die gesamte Lambda-Funktion wiederholt. Ich möchte, dass nur die fehlgeschlagenen URLs erneut versucht werden, und wenn (nach einem zweiten Versuch) sie immer noch fehlschlagen, rufen Sie eine feste URL auf, um einen Fehler zu protokollieren. Lambda Python Pool.map und urllib2.urlopen: Nur fehlerhafte Prozesse wiederholen, nur Fehler protokollieren

Dies ist der Code, wie es derzeit sitzt (mit einigen Details entfernt), nur arbeiten, wenn alle URLs sind:

from __future__ import print_function 
import urllib2 
from multiprocessing.dummy import Pool as ThreadPool 

import hashlib 
import datetime 
import json 

print('Loading function') 

def lambda_handler(event, context): 

    f = urllib2.urlopen("https://example.com/geturls/?action=something"); 
    data = json.loads(f.read()); 

    urls = []; 
    for d in data: 
     urls.append("https://"+d+".example.com/path/to/action"); 

    # Make the Pool of workers 
    pool = ThreadPool(4); 

    # Open the urls in their own threads 
    # and return the results 
    results = pool.map(urllib2.urlopen, urls); 

    #close the pool and wait for the work to finish 
    pool.close(); 
    return pool.join(); 

Ich versuchte the official documentation lesen, aber es scheint ein wenig bei der Erklärung der map Funktion zu fehlen Spezifische Erklärung der Rückgabewerte.

Mit der urlopen Dokumentation Ich habe versucht, meinen Code auf die folgende Modifikation:

from __future__ import print_function 
import urllib2 
from multiprocessing.dummy import Pool as ThreadPool 

import hashlib 
import datetime 
import json 

print('Loading function') 

def lambda_handler(event, context): 

    f = urllib2.urlopen("https://example.com/geturls/?action=something"); 
    data = json.loads(f.read()); 

    urls = []; 
    for d in data: 
     urls.append("https://"+d+".example.com/path/to/action"); 

    # Make the Pool of workers 
    pool = ThreadPool(4); 

    # Open the urls in their own threads 
    # and return the results 
    try: 
    results = pool.map(urllib2.urlopen, urls); 
    except URLError: 
    try:        # try once more before logging error 
     urllib2.urlopen(URLError.url); # TODO: figure out which URL errored 
    except URLError:     # log error 
     urllib2.urlopen("https://example.com/error/?url="+URLError.url); 

    #close the pool and wait for the work to finish 
    pool.close(); 
    return true; # always return true so we never duplicate successful calls 

Ich bin mir nicht sicher, ob ich richtig bin Ausnahmen zu tun, die Art und Weise, oder wenn ich selbst machen Python-Ausnahmedarstellung korrekt. Auch hier ist mein Ziel Ich möchte es nur die fehlgeschlagenen URLs versuchen, und wenn (nach einem zweiten Versuch) es immer noch fehlschlägt, rufen Sie eine feste URL, um einen Fehler zu protokollieren.

Antwort

0

Ich fand die Antwort dank a "lower-level" look at this question I posted here.

Die Antwort war meine eigene benutzerdefinierte Wrapper zum urllib2.urlopen Funktion zu erstellen, da jeder Thread selbst benötigt try {} catch ‚sein d statt der ganzen Sache. Diese Funktion sah aus wie so:

def my_urlopen(url): 
    try: 
     return urllib2.urlopen(url) 
    except URLError: 
     urllib2.urlopen("https://example.com/log_error/?url="+url) 
     return None 

I über der def lambda_handler Funktionsdeklaration setzen, dass, dann kann ich das ganze try/catch in sich hieraus ersetzen:

try: 
    results = pool.map(urllib2.urlopen, urls); 
except URLError: 
    try:        # try once more before logging error 
     urllib2.urlopen(URLError.url); 
    except URLError:     # log error 
     urllib2.urlopen("https://example.com/error/?url="+URLError.url); 

Um dies:

results = pool.map(my_urlopen, urls); 

QED

Verwandte Themen