Поймать исключение при использовании Python с оператором - PullRequest
238 голосов
/ 03 апреля 2009

К своему стыду, я не могу понять, как обрабатывать исключения для оператора python 'with'. Если у меня есть код:

with open("a.txt") as f:
    print f.readlines()

Я действительно хочу обработать исключение "файл не найден", чтобы что-то сделать. Но я не могу написать

with open("a.txt") as f:
    print f.readlines()
except:
    print 'oops'

и не могу написать

with open("a.txt") as f:
    print f.readlines()
else:
    print 'oops'

Заключение 'with' в оператор try / кроме больше не работает: исключение не вызывается. Что я могу сделать, чтобы обработать ошибку внутри оператора with с помощью Pythonic?

Ответы [ 4 ]

218 голосов
/ 03 апреля 2009
from __future__ import with_statement

try:
    with open( "a.txt" ) as f :
        print f.readlines()
except EnvironmentError: # parent of IOError, OSError *and* WindowsError where available
    print 'oops'

Если вы хотите, чтобы обработка ошибок отличалась от вызова open и рабочего кода, который вы могли бы сделать:

try:
    f = open('foo.txt')
except IOError:
    print('error')
else:
    with f:
        print f.readlines()
63 голосов
/ 23 мая 2011

Лучший "Pythonic" способ сделать это, используя оператор with, указан в Примере №6 в PEP 343 , который дает фон оператора.

@contextmanager
def opened_w_error(filename, mode="r"):
    try:
        f = open(filename, mode)
    except IOError, err:
        yield None, err
    else:
        try:
            yield f, None
        finally:
            f.close()

Используется следующим образом:

with opened_w_error("/etc/passwd", "a") as (f, err):
    if err:
        print "IOError:", err
    else:
        f.write("guido::0:0::/:/bin/sh\n")
49 голосов
/ 25 июля 2015

Перехват исключения при использовании оператора Python 'with'

Оператор with был доступен без __future__ import начиная с Python 2.6 . Вы можете получить его как уже в Python 2.5 (но на данный момент пришло время обновить!) С:

from __future__ import with_statement

Вот самое близкое, что можно исправить. Вы почти у цели, но у with нет предложения except:

with open("a.txt") as f: 
    print(f.readlines())
except:                    # <- with doesn't have an except clause.
    print('oops')

Метод __exit__ диспетчера контекста, если он вернет False, вызовет ошибку по окончании. Если он вернет True, он будет подавлен. Встроенный open __exit__ не возвращает True, поэтому вам нужно просто вставить его в попытку, кроме блока:

try:
    with open("a.txt") as f:
        print(f.readlines())
except Exception as error: 
    print('oops')

И стандартный шаблон: не используйте голый except:, который ловит BaseException и все другие возможные исключения и предупреждения. Будьте как минимум так же конкретны, как Exception, и для этой ошибки, возможно, поймайте IOError. Только ловить ошибки, которые вы готовы обрабатывать.

Так что в этом случае вы бы сделали:

>>> try:
...     with open("a.txt") as f:
...         print(f.readlines())
... except IOError as error: 
...     print('oops')
... 
oops
0 голосов
/ 04 апреля 2018

прибегнуть к стандартной обработке исключений

try:
    with open("a.txt") as f:
        #business as usual
except Exception as e:
    print "oops, handle exception: ", e
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...