Как запросить у пользователя ввод при возникновении исключения?

#python #exception #math

#python #исключение #математика

Вопрос:

Я создаю код для решения квадратичной формулы и нуждаюсь в обработке исключений, чтобы были обнаружены отсутствующие аргументы командной строки. В except IndexError: блоке вместо выхода из программы вы должны использовать input() , чтобы запросить у пользователя недостающие входные данные. Это не работает со следующим кодом. У кого-нибудь есть идеи?

 from math import sqrt
import sys

print('This program will solve the quadratic formula with given values, please enter below.')

try:
    a=float(sys.argv[1]) #first system argument
    b=float(sys.argv[2]) #second system argument 
    c=float(sys.argv[3]) #third system argument
    d=b**2-4*a*c #discriminant
    x1=((-b sqrt(d))/2*a) #first solution
    x2=((-b-sqrt(d))/2*a) #second solution
except IndexError:
    raise IndexError(
        'Oops! Looks like you have not entered all values. Try again.') #request user input
    a=input(sys.argv[1]) #first system argument
    b=input(sys.argv[2]) #second system argument 
    c=input(sys.argv[3]) #third system argument
    d=b**2-4*a*c #discriminant
    x1=((-b sqrt(d))/2*a) #first solution
    x2=((-b-sqrt(d))/2*a) #second solution
    
print(f'The quadratic formula with used a,b,c values gives two roots {x1:.2f} and {x2:.2f}')
  

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

1. Вы перехватили исключение и снова вызвали его. Удалить raise IndexError .

2. sys.argv это список, содержащий все заданные аргументы командной строки. Если вы не указали правильные аргументы при запуске программы, они волшебным образом не появятся, как только вы попытаетесь обработать исключение. Вместо этого изучите использование input() для взаимодействия с пользователем.

3. После того, как вы попали в except блок, с вами покончено sys.argv . Вы запрашиваете у пользователя значение напрямую. Проще всего просто выйти из программы и заставить пользователя передать правильные аргументы в первую очередь.

4. Используйте argparse модуль для обработки аргументов командной строки (и связанных с ними ошибок).

5. Прежде чем делать что-либо еще, проверьте длину sys.argv и убедитесь, что было предоставлено правильное количество аргументов, а если нет, используйте input() для их получения ) или просто распечатайте сообщение об ошибке и завершите работу).

Ответ №1:

Я вижу несколько способов улучшить исходный код:

  • Следующие инструкции raise никогда не выполняются
  • Преобразование строки через float() может вызвать ValueError
  • Если указано менее 3 аргументов, то sys.argv[n] будет выдана ошибка
  • Вы должны повторно проверять повторно введенные входные данные, пока они не станут правильными.
  • Вы не должны запускать повторный ввод правильных значений, если у более поздних возникают проблемы.
  • Если ваш дискриминант d отрицательный, sqrt() выдаст ValueError
  • Сделайте свой код СУХИМ (не повторяйтесь), разложив логику проверки.
  • Вам нужен какой-то способ сделать вывод.

Следующий код исправляет это с помощью:

  • Добавление метода validate для более СУХОГО и проверки ввода и обработки ValueError .
  • Обработайте 3 аргумента по порядку с помощью итератора, который возвращает » если не указан, который будет обрабатывать метод validate.
  • Тест на отрицательный дискриминант.
 from math import sqrt
import sys

print('This program will solve the quadratic formula with given values, please enter below.')

def validate(name, value):
    try:
        return float(value)
    except ValueError:
        new_value = input(f"Entered a value for {name}: ")
        return validate(name, new_value)

args = iter(sys.argv)
a = validate('a', next(args, ''))
b = validate('b', next(args, ''))
c = validate('c', next(args, ''))
d=b**2-4*a*c #discriminant
if d >= 0 :
    x1=((-b sqrt(d))/2*a) #first solution
    x2=((-b-sqrt(d))/2*a) #second solution
    print(f"the roots {x1} and {x2}")
else:
    print("the equation has no real-valued solutions")
  

Ответ №2:

Вы создаете исключение un внутри блока catch:

 except IndexError:
  raise IndexError(
    'Oops! Looks like you have not entered all values. Try again.')
  

Вы можете удалить его и запросить у пользователя это сообщение, используя input() или что-то подобное. например:

 except IndexError:

    a= input('Oops! Looks like you have not entered all values. Enter the value again.')