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

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

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

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

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

и не может писать

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

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

Ответ 1

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'

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

try:
    f = open('foo.txt')
except IOError:
    print('error')
else:
    with f:
        print f.readlines()

Ответ 2

Лучший способ "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")

Ответ 3

Поймать исключение при использовании Python с оператором

Оператор with был доступен без импорта __future__ начиная с 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

Ответ 4

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

try:
    with open("a.txt") as f:
        #business as usual
except Exception as e:
    print "oops, handle exception: ", e