2014-07-08 8 views
9

Sto provando a carpire alcune informazioni da pagine web che sono incoerenti su dove si trovano le informazioni. Ho il codice per gestire ognuna delle diverse possibilità; quello che voglio è provarli in sequenza, poi se nessuno di loro funziona mi piacerebbe fallire con grazia e andare avanti.Try/except Python: provare più opzioni

cioè in pseudo-codice:

try: 
    info = look_in_first_place() 
otherwise try: 
    info = look in_second_place() 
otherwise try: 
    info = look_in_third_place() 
except AttributeError: 
    info = "Info not found" 

ho potuto fare questo con istruzioni try nidificate, ma se ho bisogno di 15 possibilità di provare allora io bisogno di 15 livelli di rientro!

Questa sembra una domanda abbastanza banale che mi sembra che mi manchi qualcosa, ma l'ho cercata nel terreno e non riesco a trovare nulla che sembri equivalente a questa situazione. Esiste un modo sensato e pitonico per farlo?

EDIT: Come (piuttosto bene) la soluzione di Giovanni sotto solleva, per brevità ho scritto ogni ricerca sopra come una singola chiamata di funzione, mentre in realtà di solito è un piccolo blocco di BeautifulSoup chiama come soup.find('h1', class_='parselikeHeader'). Ovviamente potrei completare queste funzioni, ma sembra un po 'poco elegante con blocchi così semplici - scuse se la mia stenografia cambia il problema.

Questa può essere un'illustrazione più utile:

try: 
    info = soup.find('h1', class_='parselikeHeader').get('href') 
if that fails try: 
    marker = soup.find('span', class_='header') 
    info = '_'.join(marker.stripped_strings) 
if that fails try: 
    (other options) 
except AttributeError: 
    info = "Info not found" 
+0

perché avete bisogno di un blocco try/tranne, utilizzare se elif altro –

+0

Grazie Padraic, ma oltre a un istinto di favorire EAFP sopra LYBL, io non sono sicuro che sarei in grado di prevedere se le condizioni del per verificare come potrebbe andare storto in molti modi diversi, quindi gestire una gamma limitata ma ampia di eccezioni sembrava una scelta naturale. – user3816044

+0

find sarà vuoto se non corrisponde a nulla, quindi se find ... sarà True solo se c'è una corrispondenza, quindi se elif else funzionerebbe. Potresti mettere tutti i pattern in una lista e passarci sopra usando un controllo if e un altro se nessuno corrisponde a –

risposta

8

Se ogni ricerca è una funzione separata, è possibile memorizzare tutte le funzioni in un elenco e quindi iterazioni su uno per uno.

lookups = [ 
    look_in_first_place, 
    look_in_second_place, 
    look_in_third_place 
] 

info = None 

for lookup in lookups: 
    try: 
     info = lookup() 
     # exit the loop on success 
     break  
    except AttributeError: 
     # repeat the loop on failure 
     continue 

# when the loop is finished, check if we found a result or not 
if info: 
    # success 
else: 
    # failure 
+0

Mi piace, ma al momento il codice di ricerca non è in realtà in funzioni separate ma di solito è 2-3 righe di chiamate BeautifulSoup. Suppongo che potrei scrivere wrapper per tutte le possibilità, ma questo sembra eccessivo visto che sto controllando diverse informazioni, ognuna delle quali potrebbe avere diverse lookup da provare ... La strategia list sembra molto Pythonic anche se posso usare questo se io non c'è una soluzione migliore. – user3816044

+0

Anche averci pensato, farlo in questo modo significherebbe che le funzioni successive potrebbero essere utili solo se chiamate nell'ordine specifico specificato dalla lista (se, ad esempio, voglio rendere ogni tentativo successivo più permissivo). Avere funzioni in giro che producono dati errati a meno che non vengano utilizzati subito dopo che un'altra funzione sembra essere una pericolosa strategia di incapsulamento? – user3816044

Problemi correlati