попробуйте/кроме и контекстные менеджеры

#python #exception

Вопрос:

Я пытаюсь сделать свои блоки try/except как можно меньше. Однако я не знаю, как согласовать это с потенциально длительным with блоком:

 try:
    with db.connect() as connection:
        # many lines interacting with the database
        # and more lines
        # and yet more lines

except ConnectionError:
 

Есть ли способ написать попытку/исключение, чтобы это было не так долго?

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

 try:
    with db.connect() as connection:
        do_stuff(connection)
except ConnectionError:
 

…но, похоже, должен быть способ сделать это в меньшем количестве строк.

Комментарии:

1. Я бы, вероятно, выбрал разработку программного обеспечения -там больше приветствуются вопросы, касающиеся чувствительности дизайна и мнения, в то время как переполнение стека предпочитает иметь дело с конкретным и конкретным и избегать вопросов мнения или вкуса. См. Руководство по выбору сайта Stack Exchange, на каких сайтах по информатике / программированию Stack Exchange я размещаю публикации?

2. Вызов функции, вероятно, является лучшим решением.

3. Я бы посоветовал Бармену, вызов функции уместен в большинстве случаев. За исключением случаев, когда этот код обслуживает запросы, тогда было бы лучше поддерживать пул соединений

Ответ №1:

На самом деле вам не нужно вставлять with утверждение в try утверждение, если db.connect это единственное, что может вызвать ConnectionError . Если есть ошибка подключения, то закрывать соединение не нужно.

 try:
    connection = db.connect()
except ConnectionError:
    ...

with connection:
    ...
 

Утверждение заботится не о призыве к db.connect самому with себе, а о призывах к connection.__enter__ и connection.__exit__ .

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


Если вам не нравится идея иметь возможность что-то connection делать между назначением и with оператором, вы можете использовать an ExitStack для немедленного ввода контекста. Например,

 from contextlib import ExitStack


with ExitStack() as es:
    try:
        connection = es.enter_context(db.connect())
    except ConnectionError:
        ...

    # do stuff with the connection
 

Комментарии:

1. А-ха! Это именно то, что я искал. Спасибо!