2012-06-28 21 views
14

Dopo un breve dibattito con qualcuno sulla gestione delle eccezioni in Python - ha scatenato dalla manipolazione di un oggetto di coda - ho pensato di buttare là fuori ...Python: Queue.Empty Gestione delle eccezioni

METODO 1:

import Queue 

q = Queue.Queue() 

try: 
    task=q.get(False) 
    #Opt 1: Handle task here and call q.task_done() 
except Queue.Empty: 
    #Handle empty queue here 
    pass 

#Opt2: Handle task here and call q.task_done() 

METODO 2:

import Queue 

q = Queue.Queue() 

if q.empty(): 
    #Handle empty queue here 
else: 
    task = q.get() 
    #Handle task here 
    q.task_done() 

un argomento è che il metodo 1 è sbagliato perché la coda di essere vuota non è un errore, e quindi non deve essere maneggiato con un'eccezione Queue.Empty. Inoltre, potrebbe rendere più difficile il debugging se codificato in questo modo se si considera che la parte relativa alla gestione delle attività potrebbe essere potenzialmente grande.

L'altro argomento è che in entrambi i casi è accettabile in Python e che la gestione del compito al di fuori del try/tranne potrebbe aiutare il debug in caso di manipolazione compito è di grandi dimensioni, anche se d'accordo che questo potrebbe sembrare più brutto di utilizzare il metodo 2.

Opinioni?

AGGIORNAMENTO: un po 'più di informazioni dopo la risposta 1 è venuto attraverso .... Il dibattito è stato avviato dopo il metodo 1 stava usando in qualche codice multithreaded. In tal caso, il codice acquisirà il blocco (da un oggetto threading.Lock) e lo rilascerà una volta che l'attività è ritornata o Queue.Empty viene generato

UPDATE 2: Non era noto a entrambi che il l'oggetto della coda era thread-safe. Sembra che provare/eccetto sia la strada da percorrere!

+1

Non vedo come un blocco cambia la risposta, inoltre non capisco perché ha bisogno di un blocco, la coda è già thread-safe. –

risposta

26

Il metodo 2 è errato perché si sta eseguendo un'operazione in due passaggi quando potrebbe essere eseguita in uno. Nel metodo 2, controlli se la coda è vuota, e poi più tardi (molto presto, ma ancora dopo), prova ad ottenere l'oggetto. Cosa succede se hai due thread che tirano oggetti dalla coda? Get() potrebbe ancora fallire con una coda vuota. Cosa succede se un articolo viene aggiunto alla coda dopo aver verificato che fosse vuoto? Queste sono le piccole finestre di opportunità in cui gli errori si insinuano nel codice concorrente.

Farlo in un solo passaggio, è di gran lunga la scelta migliore.

import Queue 

q = Queue.Queue() 

try: 
    task = q.get(False) 
except Queue.Empty: 
    # Handle empty queue here 
    pass 
else: 
    # Handle task here and call q.task_done() 

Non rimanere incastrato su "le eccezioni dovrebbero essere errori". Le eccezioni sono semplicemente un altro canale di comunicazione, usali. Utilizzare la clausola "else" qui per restringere l'ambito della clausola di eccezione.

3

Se questa è multithreaded/multiprocessed codice (come è una buona ragione per usare le code in ogni caso), quindi sicuramente il metodo 1. Tra il q.empty() chiamata e la chiamata q.get(), il Jack di Cuori avrebbe potuto rubato le vostre crostate!

+0

Il dibattito è stato avviato dopo l'utilizzo del metodo 1 in un codice multithread. In tal caso, il codice acquisirà il blocco (da un oggetto threading.Lock) e lo rilascerà una volta che l'attività viene restituita o Queue.Empty viene lanciato ...... stessa opinione? – user1014903

+0

mantieni il codice di errorhandling il più stretto possibile - chiama 'get' e verifica subito dopo l'errore. non c'è bisogno di incorporare il resto del codice nel tentativo ... –

2

Un argomento è che il metodo 1 è errata perché la coda sia vuota non è un errore, e quindi non deve essere maneggiato con eccezione Queue.Empty

Un'eccezione non è necessariamente un "errore" , è un meccanismo generale di controllo del flusso ed è usato in questo modo in alcuni casi (SysExit, StopIteration, ecc.).

La buona domanda qui è: quale sarà il caso più comune - coda vuota o non vuota. Se non lo sai per certo, vuoi AskBeforeYouLeap, perché è molto probabilmente più economico.