Подтвердить что ты не робот

Перерыв или выход из заявления "с"?

Я бы просто хотел выйти из инструкции with при определенных условиях:

with open(path) as f:
    print 'before condition'
    if <condition>: break #syntax error!
    print 'after condition'

Конечно, вышесказанное не работает. Есть ли способ сделать это? (Я знаю, что я могу инвертировать условие: if not <condition>: print 'after condition' - любым способом, как указано выше?)

4b9b3361

Ответ 1

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

def do_it():
    with open(path) as f:
        print 'before condition'
        if <condition>:
            return
        print 'after condition'

Ответ 2

with дает вам проблемы? Бросьте больше with -возможных объектов в проблему!

class fragile(object):
    class Break(Exception):
      """Break out of the with statement"""

    def __init__(self, value):
        self.value = value

    def __enter__(self):
        return self.value.__enter__()

    def __exit__(self, etype, value, traceback):
        error = self.value.__exit__(etype, value, traceback)
        if etype == self.Break:
            return True
        return error

Просто оберните выражение, которое вы собираетесь в with, с fragile и raise fragile.Break, чтобы вырваться в любую точку!

with fragile(open(path)) as f:
    print 'before condition'
    if condition:
        raise fragile.Break
    print 'after condition'

Преимущества этой установки

  • Использует with и только with; не обертывает вашу функцию в семантически вводящий в заблуждение один цикл "цикл" или узкоспециализированную функцию и не заставляет вас выполнять дополнительную обработку ошибок после with.
  • Сохраняет ваши локальные переменные, вместо того, чтобы передавать их в функцию обертки.
  • Вкладываемые!

    with fragile(open(path1)) as f:
        with fragile(open(path2)) as g:
            print f.read()
            print g.read()
            raise fragile.Break
            print "This wont happen"
        print "This will though!"
    

    Таким образом, вам не нужно создавать новую функцию для обертывания внешнего with, если вы хотите, чтобы оба они сломались.

  • Не требует реструктуризации вообще: просто оберните то, что у вас уже есть с fragile, и вам хорошо идти!

Недостатки этой настройки

  • Фактически не используется оператор break. Не могу выиграть их все;)

Ответ 3

Я думаю, вам нужно просто перестроить логику:

with open(path) as f:
    print 'before condition checked'
    if not <condition>:
        print 'after condition checked'

Ответ 4

Так как break может возникать только внутри цикла, ваши параметры несколько ограничены внутри with до:

  • return (put "with" + связанные операторы внутри функции)
  • выход (залог из программы - возможно, не идеальный)
  • исключение (генерировать исключение внутри "с", уловить ниже)

Наличие функции и использование return, вероятно, самое чистое и простое решение здесь, если вы можете изолировать with и связанные с ним операторы (и ничего больше) внутри функции.

В противном случае создайте исключение внутри with, если необходимо, поймайте ниже/вне with, чтобы продолжить остальную часть кода.

Обновление: Как предлагает OP в комментариях ниже (возможно, tonuge в щёке?), можно также обернуть оператор with внутри цикла, чтобы заставить break работать, хотя это было бы семантически вводить в заблуждение. Поэтому, хотя рабочее решение, вероятно, не то, что было бы рекомендовано).

Ответ 5

Вы можете поместить все внутри функции, а когда условие истинно, вызовите возврат.

Ответ 6

f = open("somefile","r")
for line in f.readlines():
       if somecondition: break;
f.close()

Я не думаю, что вы можете вырваться из-за... вам нужно использовать цикл...

[edit] или просто используйте метод функции, упомянутый другими

Ответ 7

как сокращенный фрагмент:

class a:
    def __enter__(self):
        print 'enter'
    def __exit__(self ,type, value, traceback):
        print 'exit'

for i in [1]:
    with a():
        print("before")
        break
        print("after")

...

enter
before
exit

Ответ 8

Это древний вопрос, но это приложение для удобной идиомы "разрываемой видимости". Просто вставьте свой оператор with внутри:

for _ in (True,):
    with open(path) as f:
        print 'before condition'
        if <condition>: break
        print 'after condition'

Эта идиома создает "цикл", всегда выполняемый ровно один раз, с единственной целью - заключить блок кода внутри области действия, который может быть разбит условно. В случае OP это был вызов диспетчера контекста, который должен быть заключен, но это может быть любая ограниченная последовательность операторов, которая может потребовать условного выхода.

Принятый ответ в порядке, но этот метод делает то же самое без необходимости создавать функцию, которая не всегда удобна или желательна.