Using "Try and Exception" for validating data

(https://gist.github.com/52bacb772d59802e3c689ad3ff13f9d1)

I always have a problem with try and exception. I don’t know how to adapt it properly, even though I try to search examples of using.

For this exercise:
When creating a patient’s data, I like to validate if the sex and smoker are integer and the values should be 0 or 1 only.

sex : 0 for Female, 1 for Male
smoker : 0 for non-smoker, and 1 for smoker.

if not correct, the init should not pass all the parameter and raise exception

class Error(Exception):
  pass
class ZerooronevalueError(Error):
  pass
class NumericalvalueError(Error):
  pass
class Patient:
  def __init__(self, name, age, sex, bmi, num_of_children, smoker):
    self.name = name
    self.age = age
    self.sex = sex
    self.bmi = bmi
    self.num_of_children = num_of_children
    self.smoker = smoker
    try:
      if not isinstance(self.sex, int):
        raise NumericalvalueError
      if self.sex != 0 or self.sex != 1:
        raise ZerooronevalueError
    except NumericalvalueError:
      print("Sex should be numerical value.")
    except ZerooronevalueError:
      print("Sex can be only '0' for Female or '1' for Male.")

and I wrote another method

  def patient_profile(self):
    patient_information = {}
    patient_information['Name'] = self.name
    patient_information['Age'] = self.age
    patient_information['Sex'] = self.sex
    patient_information['BMI'] = self.bmi
    patient_information['Number of Children'] = self.num_of_children
    patient_information['Smoker'] = self.smoker
    return patient_information

When I run the code as follows;

patient2 = Patient("Doraemon", 25, 'male', 22.2, 0, 0)
print(patient2.patient_profile())

It raised exception, but still pass on the parameter. Thus, when I called patient_profile() method, I still got the information that ‘Sex’ : 'Male.

Sex should be numerical value.
{'Name': 'Doraemon', 'Age': 25, 'Sex': 'Male', 'BMI': 22.2, 'Number of Children': 0, 'Smoker': 0}

I tried to swap try, exception before assigning the parameter (self.age =age , etc.) and use else: after exception but the terminal showed that there was not age value.

Thank you everybody in advance for your suggestions.

You’ve still assigned part of your instance because of the order of execution. As for why your code runs it’s because you’ve set up ways to catch the exceptions. Therefore it’s perfectly happy to continue, you’ve handled the exception. If you wanted it to raise an error and cancel further execution of the program then re-raise the exceptions you caught, e.g.

except NumericalvalueError:
    print("Sex should be numerical value.")
    raise

Have a little nosey through the docs for a little more info about using raise-

1 Like

I have a similar question, and I believe I was working on the same Codecademy project as @ranchanakiriyapong31. This is from step 14 of the Python Classes: Medical Insurance Project. I was trying to build try-except statements for the inputs in a class and wanted to see what are best practices for validating input data type. Below is my code and as you can see, it seems very repetitive. Is there a way to make input validation more compact? Some of the internet resources I searched for often used examples with the input function, but this particular example does not use one so I wasn’t sure of a better way. Any feedback would be much appreciated.

class Patient:
  def __init__(self, name, age, sex, bmi, num_of_children, smoker):
    try:
      if isinstance(name, str):
        self.name = name
      else:
        raise TypeError
    except:
      print("Only strings are allowed for name.")
    
    try:
      if isinstance(age, int) and age >= 0:
        self.age = age
      elif isinstance(age, int) and age < 0:
        raise ValueError
      else:
        raise TypeError
    except:
      print("Only non-negative integers are allowed for age.")
      # add more parameters here
    
    try:
      if sex == 0 or sex == 1:
        self.sex = sex
      elif isinstance(sex, (float,int)):
        raise ValueError
      elif isinstance(sex, str):
        raise TypeError
    except:
      print("Only 0 or 1 is allowed for sex.")
    
    try:
      if isinstance(bmi, float) and bmi >= 0:
        self.bmi = bmi
      elif isinstance(bmi, float) and bmi < 0:
        raise ValueError
      else:
        raise TypeError
    except:
      print("Only non-negative numbers are allowed for BMI.") 
    
    try:
      if isinstance(num_of_children, int) and num_of_children >= 0:
        self.num_of_children = num_of_children
      elif isinstance(num_of_children, int) and num_of_children < 0:
        raise ValueError
      else:
        raise TypeError
    except:
      print("Only non-negative integers are allowed for number of children.")  
    
    try:
      if smoker == 0 or smoker == 1:
        self.smoker = smoker
      elif isinstance(smoker, (float, int)):
        raise ValueError
      elif isinstance(smoker, str):
        raise TypeError
    except:
      print("Only 0 or 1 is allowed for smoker status.")

Hello!
You don’t need the try…except if you have if statements to validate the types of input. For example here:

You could do away with the try…except block, as it does nothing. If I wanted to add two numbers together:

a = input("number")
b = input("number")

and I wanted to turn them into integers, I could use try…except:

try:
  int_a = int(a)
except:
  print("Only whole numbers allowed")

try…except is to be used when you want to perform an operation, but you don’t want an error thrown if the operation fails.

Thank you for your response! That makes sense. I updated this with pretty much all ‘if-then’ statements as below and I think it works fine! …But that means I didn’t really complete the exercise. I guess as an example, how would I use the ‘try-except’ statement to make sure that the correct number type is being used for, say, the age? In your response you mentioned about the int function, but how should I make sure that the number entered by the user is a non-negative integer? How are such data validations actually written in real-life applications? Do people use if-then statement the way I did or combinations of Try-Except statements?

class Patient:
  def __init__(self, name, age, sex, bmi, num_of_children, smoker):
    if isinstance(name, str):
      self.name = name
    else:
      print("Only strings are allowed for name.")
    
    if isinstance(age, int) and age >= 0:
      self.age = age
    else:
      print("Only non-negative integers are allowed for age.")
      # add more parameters here
    
    if sex == 0 or sex == 1:
      self.sex = sex
    else:
      print("Only 0 or 1 is allowed for sex.")
    
    if isinstance(bmi, float) and bmi >= 0:
      self.bmi = bmi
    else:
      print("Only non-negative numbers are allowed for BMI.") 
    
    if isinstance(num_of_children, int) and num_of_children >= 0:
        self.num_of_children = num_of_children
    else:
      print("Only non-negative integers are allowed for number of children.")  
    
    if smoker == 0 or smoker == 1:
      self.smoker = smoker
    else:
      print("Only 0 or 1 is allowed for smoker status.")

If all you want to do is the variables to a value, then I think that using if…else blocks is the way to go. In real life, one would use try…except if they wanted to perform some operation (like casting to type int). Say I wanted to make a program to order cakes. If I wanted to turn the input (string) into an integer (int) for some complex subtraction, then I might go:

a = input("Cakes")
try:
  int_a = int(a)
  number_of_cakes _to_be_scammed = a - 2
except:
  print("Only valid integers should be entered!")

Thanks again :slightly_smiling_face:
Later I may update what I wrote to use the input function. If I have questions, I shall come back!

1 Like