2016-12-28 72 views
2

我的代碼工作正常,但PyCharm在下面提到的except子句太寬泛。說實話,它也聞到了我的錯誤實現。Python:我的除外條款確實太寬泛了嗎?

當我拼湊HTML <tr>時,我也必須添加到數據庫或更新,但事先並不知道遊戲是否完成。此外,尚未完成的遊戲在某些<td>中有不同的HTML標籤,需要不同的處理。

基本上,如果我們看看match_score_stringmatch_relevant_bit,我們告訴BeautifulSoup找到一個具有某個類別的<td>。如果遊戲已經完成,這個<td>將有一個score-time sc類,如果沒有,它將有一個score-time st類。如果它有一個,它就不會有另一個。

自從我編寫try-except子句以來已經有一段時間了,但是如果我記得正確的話,我必須使用它的原因是因爲當row.find無法找到HTML時,BS會拋出錯誤並暫停所有操作目的。

PyCharm抱怨是否合理?

# Get Match Score 
try: 
    match_score_string = row.find("td", class_="score-time sc").get_text() 
    match_string_split = match_score_string.split(" - ") 
    team_a_score = int(match_string_split[0]) 
    team_b_score = int(match_string_split[1]) 
    print(team_a_score) 
    print(team_b_score) 
except: 
    team_a_score = None 
    team_b_score = None 

# Get Match URL 
try: 
    match_relevant_bit = row.find("td", class_="score-time sc") 
    match_url = match_relevant_bit.find("a").get("href") 
    match_url_done = match_url.rsplit('?JKLMN') 
    match_url = match_url_done[0] 
    match_finished = True 

except: 

    match_relevant_bit = row.find("td", class_="score-time st") 
    match_url = match_relevant_bit.find("a").get("href") 
    match_url_done = match_url.rsplit('?JKLMN') 
    match_url = match_url_done[0] 
    match_finished = False 

回答

3

你的except肯定是太寬泛了。在這些情況下,我不會否認你是否需要異常處理 - 例外情況非常惡劣,所以只要你認爲合適,就使用它們。然而,你並沒有主張你需要你的代碼來處理可以想象的異常。除了可以掩蓋各種各樣的bug之外,一個裸露的。例如如果您在以後的版本中拼錯了某個變量名:

try: 
    match_score_string = row.find("td", class_="score-time sc").get_text() 
    match_string_split = match_score_string.split(" - ") 
    team_a_score = int(match_string_spilt[0]) # oops 
    team_b_score = int(match_string_split[1]) 
    print(team_a_score) 
    print(team_b_score) 
except: 
    team_a_score = None 
    team_b_score = None 

裸節選還可以防止用戶發送KeyboardInterrupt終止程序...

這些都只是2個例子,爲什麼你不想要除了 - 因爲由此可能掩蓋的編程錯誤的數量接近無限,我沒有足夠的時間來展示所有這些;-)。

相反,你應該指定你會遇到什麼情況例外:

try: 
    match_score_string = row.find("td", class_="score-time sc").get_text() 
    match_string_split = match_score_string.split(" - ") 
    team_a_score = int(match_string_spilt[0]) # oops 
    team_b_score = int(match_string_split[1]) 
    print(team_a_score) 
    print(team_b_score) 
except AttributeError: # If no row is found, accessing get_text fails. 
    team_a_score = None 
    team_b_score = None 

這樣,像您期望你不掩蓋(太多)編程錯誤的代碼執行。你想要做的下一件事情就是儘可能地限制異常處理程序中的代碼量。

+0

另一種情況是'sys.exit()'在這種嘗試中調用時不起作用,除了塊 –

+0

@JossefHarush - 當然。或者失敗的'assert'語句或......任何東西。 :-) – mgilson

+0

您會如何處理外部異常,比如'KeyboardInterrupt'或任何'RuntimeError',而不是專門處理'try'子句中的代碼引發的異常?傳統的異常處理是處理'try'中的「直接」錯誤(比如'find'或者一個不可能的'int'類型),似乎OP想要以同樣的方式處理所有這些異常,但正如你寫的那樣,外部異常例如'KeyboardInterrupt'應該被不同的處理。 –

0

Try/except從句很棒。聽起來你不太經常使用它們。

try/except塊可以幫助您避免複雜如果繼續之前檢查的條件語句,或代碼中有時會令它不清楚你是什麼嘗試 ING做(見我做什麼有:P)。

有幾個例外,你可能會拖出你的代碼,其中一些可能比其他人更可能。見下:

try: 
    # This first line could have an AttributeError in two places 
    #  Maybe the row didn't parse quite correctly? find() won't work then. 
    #  Maybe you didn't find any elements? get_text() won't work then. 
    match_score_string = row.find("td", class_="score-time sc").get_text() 
          ^        ^
    # Same as here, you could get an AttributeError if match_score_string isn't a string. 
    #  I would say that isn't very likely in this case, 
    #  Especially if you handle the above line safely. 
    match_string_split = match_score_string.split(" - ") 

    # If either of these split strings contains no matches, you'll get an IndexError 
    # If either of the strings at the index contain letters, you may get a ValueError 
    team_a_score = int(match_string_split[0]) 
    team_b_score = int(match_string_split[1]) 

    # Theoretically, if you caught the exception from the above two lines 
    #  you might get a NameError here, if the variables above never ended up being defined. 
    print(team_a_score) 
    print(team_b_score) 
except: 
    # Can't really imagine much going wrong here though. 
    team_a_score = None 
    team_b_score = None 

正如你可能想象的那樣,捕獲幾種類型的異常可能更有用。這取決於您輸入的複雜性。

多個try/except塊在這裏也會有好處,特別是在處理這種情況下,如果發現錯誤並需要繼續執行該塊內的其餘代碼。

+0

謝謝Vasili。如果我正確理解@ mgilson的答案,這證實了我的想法,我們的目標是一次只捕獲* less *錯誤,而不是* more *。另外,我認爲你包含的代碼不能處理第二種類型的'​​',這是必需的,因爲在這種情況下我必須向數據庫寫入不同的數據。 – zerohedge

+0

是的,理想情況下,您希望儘可能少地在'try'塊中發生。我只舉了一個例子來說明它如何分解成多個例外。取決於你想如何處理事情。 –