2015-09-21 4 views
2

Акт попытки открыть файл в Python может вызвать исключение. Если я открываю файл с помощью оператора with, могу ли я уловить исключения, вызванные вызовом open и связанным с ним вызовом __enter__, не перехватывая исключения, вызванные кодом в блоке with?Как я могу перехватывать исключения, вызванные `with open (filename)` в Python?

try: 
    with open("some_file.txt") as infile: 
     print("Pretend I have a bunch of lines here and don't want the `except` below to apply to them") 
     # ...a bunch more lines of code here... 
except IOError as ioe: 
    print("Error opening the file:", ioe) 
    # ...do something smart here... 

Этот вопрос отличается от this older one в том, что старший собирается писать менеджер контекста, а не с помощью знакомого with open.

+1

Вы действительно хотите, чтобы поймать исключения брошенный '__enter__', или вы хотите поймать исключения, вызванные самим вызовом' open'? – BrenBarn

+0

@BrenBarn, хороший момент. Я не рассматривал их как разные, но, полагаю, они должны быть. Наверное, я хочу исключений из любого места, но меня больше беспокоит всякий фрагмент кода, создающий исключение, как «IOError». – kuzzooroo

ответ

2

Могу ли я поймать исключения, вызванные открытым вызовом, и связанный с ним вызов __enter__ без исключения исключений, вызванных кодом внутри блока?

Да:

#!/usr/bin/env python3 
import contextlib 

stack = contextlib.ExitStack() 
try: 
    file = stack.enter_context(open('filename')) 
except OSError as e: 
    print('open() or file.__enter__() failed', e) 
else: 
    with stack: 
     print('put your with-block here') 

с функцией по умолчанию open(), __enter__() не должно вызывать каких-либо интересных исключений, и поэтому код можно упростить:

#!/usr/bin/env python  
try: 
    file = open('filename') 
except OSError as e: 
    print('open() failed', e) 
else: 
    with file: 
     print('put your with-block here') 
3

Если ошибка связана с открытием файла (например, если файл не существует), он будет поднят вызовом только open, а не __enter__. В этом случае вы можете поймать его, отделяя open вызова от блока с:

try: 
    myFile = open('some_file.txt') 
except IOError: 
    print("Oh my snakes and garters!") 

with myFile: 
    # do stuff 

# This will be True 
print(myFile.closed) 

Поскольку вопрос вы связаны (и другие связанные с них) предполагают, вы можете на самом деле не отдельные исключения в __enter__ из исключений в блок with. Однако по этой причине в большинстве случаев менеджер контекста, который пытается сделать сложный материал, который может вызвать исключение в __enter__, вероятно, является хрупким дизайном. Я думаю, file.__enter__ просто возвращает файл (как предложено this page), хотя я не могу найти документацию, гарантирующую это.