Все те же грабли про безусловный переход

Fudthhh

Ребята. Давайте без лишнего срача. Возникла проблема, которую я не могу решить. Есть программа тело которой зацикленно, т.е. когда программа выполнит весь алгоритм, запускается заново. В любой момент мне нужно вернуться на один из предыдущих шагов, чтобы что то поменять. Делаю я с помощью прерывания KeyboardInterrupt и возвращаюсь на нужную точку. Соль в том, что из за частых прерываний, функции рекурсируют. Для наглядности напишу пример.
def Abort():
    val=int(input('Выбирите куда нужно вернуться'))
    return main(val)
 
 
def main(progress=0)
    try:
        while True:
            if progress==1:
                step1()
            if progress==2:
                step2()
                .
                .
            if progress==N:
                stepN()
    except KeyboardInterrupt:
        return Abort()
PS - Я недавно изучаю программирование, поэтому не судите строго за то что я написал этот быдло код. Надеюсь на адекватное понимание.
14 ответов

Fudthhh

Попробуй весь блок try-except снаружи обернуть в бесконечный цикл, в начале которого считывается параметр. Тогда обойдется без лишних вызовов.


Fudthhh

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


Fudthhh

Не понимаю, как одно мешает другому. Обработка ошибок — отдельно, цикл жизни приложения — отдельно.


Fudthhh

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


Fudthhh

Грубо, о чем говорил я (не проверял):
def main()
    progress = 0
    while True:
        try:
            while True:
                if progress == 1:
                    step1()
                if progress == 2:
                    step2()
                    .
                    .
                if progress == N:
                    stepN()
        except KeyboardInterrupt:
            progress = int(input('Выбирите куда нужно вернуться'))
Разделить на функции по вкусу.


Fudthhh

Проблема в том, что она так же может выскочить в функциях stepX(), или в сторонних subprocess'ax, не уверен что это будет разумно везде это прописывать. Но я попробую. Может есть еще варианты?


Fudthhh

Проблема в том, что она так же может выскочить в функциях stepX()
Кто «она»?Короче говоря, хочется услышать более детальную логику обработки прерываний и исключений, которую хочется реализовать. А то как-то фрагментированно доносишь.


Fudthhh

Кажется тебе стоит почитать про http://pythonz.net/references/named/generator/


Fudthhh

Хорошо. Есть функция step1(). HP-это прибор. Общение идет через библиотеку visa32. val-значение которое мы заранее задали.
def step1():
    try:
        FREQ=HP.query('MEAS:RFR:FREQ:ABS?')
        if FREQ!=val:
            Abort('Несоответсвует значение')  #Не получилось значение(далее настраиваем, запускаем данную функцию снова)
        else:
            return FREQ
    except KeyboardInterrupt:
        Abort('Вызваное прерывание')          #Ручками вызвали прерывание(Возвращаемся на какой либо предыдущий шаг)
    except:
        Abort('Нет ответа от прибора')          #Прибор не ответил на команду(Возвращаемся на какой либо предыдущий шаг либо запускаем снова)
Вот одна из функций с возможными ошибками, внутри основной программы.


Fudthhh

Варианты: 1. Везде, где есть вызов Abort, кидать какое-нибудь исключение. Грязноватый прием, т.к. это похоже на управление потоком выполнения, а исключения явно не для этого. Но если в этих ситуациях все равно ничего разумного сделать нельзя — то пойдет. 2. Везде, где есть вызов Abort, возвращать специальное значение, сигнализирующее об ошибке. Этот вариант может быть менее удобным для обработки на вызывающей стороне.


Fudthhh

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


Fudthhh

Если метод исключений не подходит
Я пока не понимаю, почему исключения не подходят.
Сразу скажу, что в любую секунду нужно остановить функцию, и совершить какое либо действие.
Мы сейчас говорим о двух механизмах — ошибках, возникающих во время выполнения и о прерываниях, инициируемых пользователем. Давай не смешивать. Ошибки возникают не «в любую секунду» а «при определенных условиях». Можно кидать исключения.Касательно прерываний еще наброшу. Можно зарегистрировать обработчик сигналов и устанавливать некоторый глобальный флаг, значение которого проверять в определенных точках приложения. Тогда получаем управляемые прерывания.


Fudthhh

Хорошо. Изучу данную тему. Если что то получиться или нет. При любом результате отпишу. Спасибо.
Кажется тебе стоит почитать про http://pythonz.net/references/named/generator/
На счет генераторов и итераторов, ты немного не туда меня послал, но спасибо. Данная информация была полезна.Извините что не по теме, а как задать размер консоли по ширине и высоте? Cчитать я могу, а вот задать, информацию не нашел.


Fudthhh

Извините что не по теме, а как задать размер консоли по ширине и высоте? Cчитать я могу, а вот задать, информацию не нашел.
Какая ОС, какая консоль/эмулятор терминала?Под виндой можно так:
import os
 
os.system('mode con: cols=100 lines=40')