2014-07-08 8 views
9

Próbuję zeskrobać niektóre informacje ze stron internetowych, które nie są zgodne co do lokalizacji informacji. Mam kod do obsługi każdej z kilku możliwości; chcę je wypróbować w kolejności, a jeśli żadna z nich nie zadziała, chciałbym z wdziękiem i przejść dalej.Python try/except: próba wielu opcji

Oznacza to, że w psuedo-kod:

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" 

mogłem zrobić to z zagnieżdżonych instrukcji try, ale jeśli muszę 15 mozliwosci spróbować potem będę potrzebował 15 poziomów wcięcia!

To wydaje się dość banalne pytanie, że czuję, że czegoś brakuje, ale przeszukałem go w terenie i nie mogę znaleźć niczego, co wyglądałoby równoznacznie z tą sytuacją. Czy istnieje rozsądny i Pythoniczny sposób na zrobienie tego?

EDYCJA: Jak podchodzi rozwiązanie Johna (całkiem niezłe) poniżej, dla zwięzłości napisałem każde z powyższych wyrażeń powyżej jako pojedyncze wywołanie funkcji, podczas gdy w rzeczywistości jest to zwykle mały blok wywołań BeautifulSoup, takich jak soup.find('h1', class_='parselikeHeader'). Oczywiście mogłem owijać je funkcjami, ale wydaje się to trochę nieeleganckie w przypadku takich prostych bloków - przepraszam, jeśli mój skrót modyfikuje problem.

To może być bardziej przydatny ilustracji:

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

dlaczego trzeba spróbować/chyba, użyj jeśli elif else –

+0

Dzięki PADRAIC, ale oprócz instynktu faworyzować EAFP nad LYBL, nie jestem pewien, że będę w stanie przewidzieć, czy warunki aby sprawdzić, jak mogło się nie udać na wiele różnych sposobów, więc obsługa ograniczonej, ale szerokiej gamy wyjątków wydawała się naturalnym dopasowaniem. – user3816044

+0

find będzie puste, jeśli nie pasuje do niczego, więc jeśli find ... będzie prawdą tylko wtedy, gdy istnieje dopasowanie, więc jeśli elif będzie działał. Możesz umieścić wszystkie wzorce na liście i przeglądać je za pomocą sprawdzenia if i in else if none match –

Odpowiedz

8

Jeżeli każde wyszukiwanie jest oddzielna funkcja, można przechowywać wszystkie funkcje na liście, a następnie iteracyjne nad nimi, jeden po drugim.

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

Ja to lubię, ale w tej chwili kod odnośnika nie znajduje się w oddzielnych funkcjach, ale zwykle zawiera 2-3 linie wywołań BeautifulSoup. Przypuszczam, że mógłbym napisać wrappery dla wszystkich możliwości, ale wydaje mi się, że to przesada, ponieważ sprawdzam kilka informacji, z których każda może mieć kilka wyszukiwań do wypróbowania ... Strategia listy wydaje się być bardzo Pythonowa, więc mogę użyć to, jeśli nie ma lepszego rozwiązania. – user3816044

+0

Również o tym myśląc, zrobienie tego w ten sposób oznaczałoby, że późniejsze funkcje mogą być przydatne tylko wtedy, gdy zostaną wywołane w określonej kolejności określonej przez listę (jeśli, na przykład, chcę, aby każda kolejna próba była bardziej permisywna). Posiadanie funkcji leżących wokół, które produkują złe dane, chyba że są używane zaraz po tym, jak inna funkcja wydaje się być niebezpieczną strategią hermetyzacji? – user3816044

Powiązane problemy