2011-10-15 11 views
31
# Open new file to write 
file = None 
try: 
    file = open(filePath, 'w') 
except IOError: 
    msg = ("Unable to create file on disk.") 
    file.close() 
    return 
finally: 
    file.write("Hello World!") 
    file.close() 

Powyższy kod jest zgrywany z funkcji. Jednym z systemu użytkownika zgłasza błąd w linii:Python try: except: finally

file.write("Hello World!") 

błąd:

AttributeError: 'NoneType' object has no attribute 'write' 

pytanie jest, jeśli Python jest nie można otworzyć dany plik, „z wyjątkiem” wykonuje bloku i musi return, ale kontrola jest przenoszona do linii, która rzuca dany błąd. Wartością zmiennej "plik" jest "Brak".

Jakieś wskazówki?

Odpowiedz

67

Nie powinieneś zapisywać do pliku w bloku finally, ponieważ wszelkie zgłaszane tam wyjątki nie zostaną przechwycone przez blok except.

Bock wykonuje się, jeśli wystąpił wyjątek wywołany przez blok try. finally zawsze wykonuje wszystko, co się dzieje.

Ponadto nie powinno być potrzeby inicjowania zmiennej file na none.

Użycie return w bloku except nie pominie bloku finally. Z samej swojej natury nie można go pominąć, dlatego chcesz umieścić w nim swój kod "oczyszczenia" (tzn. Zamknąć pliki).

Tak więc, jeśli chcesz używać spróbować: z wyjątkiem: w końcu, należy robić coś takiego:

try: 
    f = open("file", "w") 
    try: 
     f.write('Hello World!') 
    finally: 
     f.close() 
except IOError: 
    print 'oops!' 

znacznie czystszy sposób robi się to za pomocą instrukcji with:

try: 
    with open("output", "w") as outfile: 
     outfile.write('Hello World') 
except IOError: 
    print 'oops!' 
+11

+1 dla 'oświadczenie with' – gecco

+0

kod jest bardzo clever.i uczyć się od niego – viprs

+1

Niestety,' with' nie jest obecna w Pythonie 2.4, więc to nie będzie działać. – SummerBreeze

0

w końcu zawsze jest wywoływana w "końcówce", nawet jeśli wystąpi wyjątek. Możesz tego użyć, aby upewnić się, że otwarte zasoby są zamknięte (na przykład połączenie DB, plik itp.).

Myślę, że źle zrozumieliście semantykę.

Twoja logika powinna znajdować się w "try", powinieneś radzić sobie z wyjątkami w bloku "except", a "finally" jest wykonywany bez względu na to, jak kończy się twoja metoda, użyj go do oczyszczenia.

1

Z wyjątkiem nie wykonuje (ponieważ typ to IOError) jest to ostatecznie część, która zgłasza inny błąd typu AttributeError, ponieważ file = None.

27

Jeśli plik nie zostanie otwarty, linia file = open(filePath, 'w') ulegnie awarii, więc nic nie zostanie przypisane do file.

Następnie klauzula except działa, ale nic nie jest w pliku, więc file.close() kończy się niepowodzeniem.

Klauzula zawsze działa, nawet jeśli wystąpił wyjątek. A ponieważ file jest wciąż Brak otrzymasz kolejny wyjątek.

Chcesz mieć klauzulę else zamiast finally dla rzeczy, które mają miejsce tylko wtedy, gdy nie było wyjątku.

try: 
     file = open(filePath, 'w') 
    except IOError: 
     msg = "Unable to create file on disk." 
     return 
    else: 
     file.write("Hello World!") 
     file.close() 

Dlaczego else? Python docs powiedzieć:

The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try ... except statement.

Innymi słowy, to nie złapie się IOError od write lub close połączeń. Co jest dobre, ponieważ wtedy powodem nie było "Nie można utworzyć pliku na dysku." - to byłby inny błąd, na który twój kod nie był przygotowany. To dobry pomysł, aby nie próbować radzić sobie z takimi błędami.

+1

+1 dla niedostatecznie użytego "else" – kindall

+0

Ale co jeśli plik file.write() podnosi wyjątek - który jest całkowicie możliwy po otwarciu, nawet chociaż został otwarty z uprawnieniami do zapisu. Najlepiej uwzględnić to w próbie: block – jenming

+1

@jenming: Cóż, prawie wszystko może podnosić wyjątki :) Powinieneś jednak naprawdę postarać się poradzić sobie tylko z wyjątkami, których się spodziewasz. Jeśli martwisz się wyjątkami od 'file.write()', włącz to w 'try'; po prostu pamiętaj, aby nie dołączać czegoś takiego jak 'file.write (" result:% s "% do_calculation())', ponieważ mogłoby to ukryć wyjątki od 'do_calculation'. –

3

jaka jest logika w tym

file.write("Hello World!")

wewnątrz klauzuli finally ?? myślę, że to musi być umieszczone w klauzuli try.

try: 
     file = open(filePath, 'w') 
     file.write("Hello World!") 
except IOError: 
     print("Unable to create file on disk.") 
finally: 
     file.close() 
0

To jest zawsze wskazane, aby napisać swoją logikę lub kod, który może rzucić wyjątek w bloku try i korzystania bloku finally do zamykania zasobów.

+0

Nie ma związku z pierwotnym pytaniem. – stackoverflowuser2010

1

można zrobić coś takiego:

try: 
    do_some_stuff() 
finally: 
    cleanup_stuff() 
1

Oto najbardziej bezpośredni rozwiązanie problemu. Używam idiomu sprawdzania dla file_obj != None w bloku finally.

Nawiasem mówiąc, powinieneś wiedzieć, że file to nazwa klasy Python, więc powinieneś wybrać inną nazwę zmiennej.

file = None 
try: 
    file = open(filePath, 'w') 
except IOError: 
    msg = ("Unable to create file on disk.") 
    file.close() 
    return 
finally: 
    if file != None: 
     file.write("Hello World!") 
     file.close() 
Powiązane problemy