Исключения и Python - PullRequest
       3

Исключения и Python

2 голосов
/ 20 июля 2011

Я очень новичок в Python, и у меня есть проблема, которую я решил решить, но она продолжает возникать. У меня что-то похожее на следующее.

def funct1()
    dosomestuff
    funct2()

def funct2()
    dosomestuff
    funct3()

def funct3()
    dosomestuff
    funct1()

def exceptionRecovery()
    checksomethings
    funct1() or funct2() or funct3()

try: 
    funct1()
except:
    exceptionRecovery()

Теперь моя проблема в том, что эта программа НИКОГДА не должна выходить. ExceptionRecovery должен проверять несколько вещей и запускать правильную функцию в зависимости от состояния некоторых различных вещей. Тем не менее, я все еще получаю сбои из программы, которая чертовски смущает меня. Может кто-нибудь показать мне, что я делаю не так?

Ответы [ 9 ]

9 голосов
/ 20 июля 2011

Вы получаете исключение переполнения стека за шанс :)? Поскольку python не имеет оптимизации рекурсии хвостового вызова, вы не можете бесконечно вкладывать вызовы функций. По этой причине вам следует подумать о том, чтобы поместить свою логику в бесконечный цикл while.

while True:
    //logic to call func1, 2, 3 or whatever
7 голосов
/ 20 июля 2011

Ваша программа по сути является бесконечно рекурсивной программой. Вы уничтожаете стек вызовов Python с предубеждением.

3 голосов
/ 20 июля 2011

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

Рассмотрим цикл while с вызовами ваших трех функций внутри. Хотя, не зная, чего вы пытаетесь достичь, будет сложно дать совет.

3 голосов
/ 20 июля 2011

Этот стиль программирования, кажется, ожидает оптимизации tail call , которая не поддерживается в Python.Стек вызовов Python отслеживает каждую функцию, которая не вернулась, и, поскольку вы просто бесконечно вызываете новые функции, вы очень быстро превысите максимальный размер стека, и ваша программа потерпит крах.

3 голосов
/ 20 июля 2011

Я ... не уверен, что полностью понимаю, почему вещи связаны друг с другом так, как они есть.В Python, по крайней мере, по моему опыту, стандартная идиома для «программы, которая выполняется вечно» выглядит примерно так:

while True:
  function_1()

То, что вы настраиваете, - это бесконечная рекурсия, которая в конечном итоге пропуститнастройка максимального уровня рекурсии интерпретатора, вызывающая исключение, которое вы не можете поймать и проигнорировать.

2 голосов
/ 20 июля 2011

Вы не должны реализовывать цикл, вызывая ваш main изнутри обработчика исключений. Попробуйте что-то вроде этого:

while True:
    try:
        func1() or func2() or func3()
    except:
        logger.exception("somthing bad happened")
1 голос
/ 20 июля 2011

Я думаю, что Джон прав, когда вы уничтожаете стек вызовов.Однако, что произойдет, если вы в первый раз нажмете на функцию exceptionRecovery, и она вызовет функцию 1 2 или 3, в любом случае она больше не находится в попытке, кроме как, и поэтому завершит работу, если она не будет в новой попытке, кроме.

1 голос
/ 20 июля 2011

Совет: использование except: очень плохо.Всегда пытайтесь указать тип исключения, которое вы перехватываете.

Проверьте этот поток о глубине рекурсии!

0 голосов
/ 20 июля 2011

Вы реализовали поток своей программы, используя продолжения . Если у вас есть фоновое программирование на Scheme или некоторых других языках, то вы, возможно, использовали этот стиль в прошлом без каких-либо негативных последствий. В Python использование стиля, основанного на продолжениях, так, как вы это сделали, в конечном итоге приведет к переполнению стека, если только ваша программа не завершится достаточно быстро, чтобы предотвратить это.

Если вы ранее полагались на оператор GOTO в своем программировании на других языках, вы должны знать, что в Python вызов функции не такой же, как «прыжок», как в GOTO, к началу этой функции в источнике.

Узнайте , как работает стек (есть много мест в Интернете, которые могут помочь вам в этом). Используйте оператор return в своем коде, чтобы избежать «неограниченного стека».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...