2015-05-05 17 views
9

Bir JSON özet akışını ayrıştıracağım kodum var. Her dizide için `for` ve` try` bloklarını birleştirmenin pythonik yolu

Ben bir koda sahip: Ben bu döngüler için gözlerimi yapar sevmiyorum

for node in parse_me: 
    # It's important that one iteration failing doesn't cause all iterations to fail. 
    try: 
     i = node['id'] # KeyError? 
     function_that_needs_int (i) # TypeError? 
     # possibly other stuff 

    except Exception as e: 
     LogErrorMessage ('blah blah blah {} in node {}'.fmt(e, node)) 

çift iç içe ben döngü durduruluyor istisnalar durdurmak gerekir çünkü sadece. Bu kodu düzleştirmenin bir yolu var mı? Sonra

def iterate_safe(parse_me, message, action): 
    for node in parse_me: 
     try: 
      action(node) 
     except Exception as e: 
      LogErrorMessage(message.fmt(e, node)) 

ve benzeri

+8

Bu bana iyi görünüyor, sorun nedir? – jonrsharpe

+0

Bu çok güzel .. Dönmeyi denemek için daha seksi buluyorum. – Maroun

+3

Yuvalama seviyesi sizi rahatsız ediyorsa, bu, öğeleri kendi işlevine taşımanın zamanıdır. –

cevap

5

Sonra yapmanız gereken şeyler

def action(node): 
    do_whatever_must_be_done_with(node) 

iterate_safe(parse_me, action, 'blah blah blah {} in node {}') 
iterate_safe(parse_me, other_action, 'spam ham {} in node {}') 
1

DÜZENLEME gibi diyoruz: orijinal soru tüm ayrıştırma işlemi dev birinde for olduğunu ima gibiydi - döngü; cevabım aşağıdaki yorumları yansıtacak şekilde değiştirildi. Bunun yerine yazma birden for -loops ait

, her biri içinde döngüler ne yapılması gerektiğini açıklayan işlevler yazmak ve her birini ile saracak onlara uygulamak için bir dekoratör yazmak, try/catch blok içermelidir for -loop vetry/catch günlüğe kaydetme mantığı. Bu biraz glglgl'ın çözümü gibi, biraz daha Pythonic (bence). Örneğin:

def apply_to_nodes_and_log_errs(node_visit_func): 
    def safe_iterating_visitor(nodes_to_parse): 
     for node in nodes_to_parse: 
      try: 
       node_visit_func(node) 
      except StandardError as e: 
       LogErrorMessage ('blah blah blah {} in node {}'.fmt(e, node)) 
    return safe_iterating_visitor 

@apply_to_nodes_and_log_errs 
def action_one(node): 
    # ... "lots of stuff" :D 

@apply_to_nodes_and_log_errs 
def action_two(node): 
    # different stuff 

Bunun yerine parçalar halinde dekoratör kırmak istiyorsanız:

def iterate_over_nodelist(node_visit_func): 
    def iterating_visitor(nodes_to_parse): 
     for node in nodes_to_parse: 
      node_visit_func(node) 
    return iterating_visitor 

def safely_visit_log_errs(node_visit_func): 
    def safe_logging_visitor(node_to_visit): 
     try: 
      node_visit_func(node) 
     except StandardError as e: 
      LogErrorMessage ('blah blah blah {} in node {}'.fmt(e, node)) 
    return safe_logging_visitor 

def apply_to_nodes_and_log_errs(node_visit_func): 
    return iterate_over_nodelist(safely_visit_log_errs(node_visit_func)) 

# ... write visit functions 

Bu da functools.wraps kullanılarak geliştirilebilir.

Standartınızın "mümkün olduğunca az sayıda girinti kullanması" durumunda, bu biraz çirkin görünebilir, ancak aslında bu oldukça Pythonic; dekoratörler yazarken oldukça az sayıda girinti seviyesinden kaçınmanın hiçbir yolu yoktur.

Son olarak, Exception ile StandardError arasında değişiklik yaptığımı unutmayın;

+0

Sorunu bize kod veren bir örnekle düzenledim. 'for' bedeninde çok fazla iş yapmak zorundadır, ancak bazen sadece bir veya iki satırdır.Bunun için tutarlı olan tek şey, döngü deyimi için her zaman ortaya çıkmaktadır. Hatalarım çoğunlukla JSON feed'inden kaynaklanıyor Kötü: Bazen veriler eksik veya tuhaf değerler alıyoruz ("int" olması gereken bir alandaki "12") ve genellikle test edilmemiş durumlarda son buluyorum. – QuestionC

+0

Bu uygulamada gördüğüm her istisna ha bir "Data's screwed" istisnası oldu, bu yüzden şu anda istisnalar geçirmekten endişelenmiyorum. Eğer istisnalarla karşılaşmaya başlarsam, yeniden düşünmek mantıklı olur, ben onları yeniden başlatmaya başlarım. – QuestionC

+0

@QuestionC Yani aslında birden fazla döngüye sahipsin, büyük bir döngü değil? Ayrıca, yine klavye-interrupt istisnası iyi bir örnektir; * hiçbir fikrin yok * ne zaman olursa olsun (kodunuzla ilgili deneyiminizden bağımsız olarak), ve * hemen hemen her zaman * onları yeniden düzenlemelisiniz. * Minimum *, 'Exception' yerine' StandardError' yakalamak çok daha iyidir. –

İlgili konular