Python - asserisci se e restituisci

7

Sto scrivendo uno script che fa qualcosa in un file di testo (quello che fa è irrilevante per la mia domanda). Quindi, prima di fare qualcosa sul file, voglio controllare se il file esiste. Posso farlo, nessun problema, ma il problema è più quello dell'estetica.

Ecco il mio codice, implementando la stessa cosa in due modi diversi.

def modify_file(filename):
    assert os.path.isfile(filename), 'file does NOT exist.'


Traceback (most recent call last):
  File "clean_files.py", line 15, in <module>
    print(clean_file('tes3t.txt'))
  File "clean_files.py", line 8, in clean_file
    assert os.path.isfile(filename), 'file does NOT exist.'
AssertionError: file does NOT exist.

o

def modify_file(filename):
    if not os.path.isfile(filename):
        return 'file does NOT exist.'


file does NOT exist.

Il primo metodo produce un output che è per lo più banale, l'unica cosa che mi interessa è che il file non esiste.

Il secondo metodo restituisce una stringa, è semplice.

Le mie domande sono: quale metodo è meglio per far sapere all'utente che il file non esiste? L'utilizzo del metodo assert sembra in qualche modo più pitonico.

    
posta Vader 29.01.2014 - 17:25
fonte

3 risposte

27

Scegli invece un'opzione terza : usa raise e un'eccezione specifica. Questa può essere una delle eccezioni integrate , oppure puoi creare un'eccezione personalizzata per il lavoro.

In questo caso, utilizzerei IOError , ma < a href="http://docs.python.org/2/library/exceptions.html#exceptions.ValueError"> ValueError potrebbe anche adattarsi:

def modify_file(filename):
    if not os.path.isfile(filename):
        raise IOError('file does NOT exist.')

L'utilizzo di un'eccezione specifica consente di aumentare le altre eccezioni per circostanze eccezionali diverse e consente al chiamante di gestire l'eccezione con garbo.

Naturalmente, molte operazioni sui file (come open() ) stessi sollevano OSError già; In primo luogo, testare esplicitamente se il file esiste potrebbe essere ridondante qui.

Non utilizzare assert ; se esegui python con il flag -O , tutte le asserzioni vengono rimosse dal codice.

    
risposta data 29.01.2014 - 17:34
fonte
7

assert è inteso per i casi in cui il programmatore che chiama la funzione ha commesso un errore, al contrario di utente . L'utilizzo di assert in tale circostanza ti consente di assicurarti che un programmatore stia utilizzando correttamente la tua funzione durante il test, ma poi lo spoglia in produzione.

Il suo valore è alquanto limitato poiché devi assicurarti di esercitare quel percorso attraverso il codice e spesso desideri gestire ulteriormente il problema con un'istruzione if separata in produzione. assert è molto utile in situazioni del tipo "Voglio risolvere il problema in modo utile se un utente lo colpisce, ma se uno sviluppatore lo colpisce, voglio che si blocchi troppo velocemente, quindi correggerà il codice che chiama questa funzione in modo errato. "

Nel tuo caso particolare, un file mancante è quasi certamente un errore dell'utente e dovrebbe essere gestito sollevando un'eccezione.

    
risposta data 29.01.2014 - 23:26
fonte
3

Da UsingAssertionsEffectively

Checking isinstance() should not be overused: if it quacks like a duck, there's perhaps no need to enquire too deeply into whether it really is. Sometimes it can be useful to pass values that were not anticipated by the original programmer.

Places to consider putting assertions:

checking parameter types, classes, or values
checking data structure invariants
checking "can't happen" situations (duplicates in a list, contradictory state variables.)
after calling a function, to make sure that its return is reasonable 

The overall point is that if something does go wrong, we want to make it completely obvious as soon as possible.

It's easier to catch incorrect data at the point where it goes in than to work out how it got there later when it causes trouble.

Assertions are not a substitute for unit tests or system tests, but rather a complement. Because assertions are a clean way to examine the internal state of an object or function, they provide "for free" a clear-box assistance to a black-box test that examines the external behaviour.

Assertions should not be used to test for failure cases that can occur because of bad user input or operating system/environment failures, such as a file not being found. Instead, you should raise an exception, or print an error message, or whatever is appropriate. One important reason why assertions should only be used for self-tests of the program is that assertions can be disabled at compile time.

If Python is started with the -O option, then assertions will be stripped out and not evaluated. So if code uses assertions heavily, but is performance-critical, then there is a system for turning them off in release builds. (But don't do this unless it's really necessary. It's been scientifically proven that some bugs only show up when a customer uses the machine and we want assertions to help there too. :-) )

    
risposta data 17.11.2016 - 15:10
fonte

Leggi altre domande sui tag