Search code examples
pythonpython-2.7error-handlingioerror

Handle multiple IO errors


I have several IO operation that I carry out on class init but they often fail with IOError. What I would like to do is delay a few hundred ms and try again until success or some defined timeout. How can I make sure each individual command succeeds before continuing/ending the loop? I assume there is a better way than an if statement for each item and a counter to check if all commands succeeded.

My current code below often fails with IOError and hangs the rest of the application.

   def __init__(self):
      print("Pressure init.")
      self.readCoefficients()

   def readCoefficients(self):
      global a0_MSB;
      global a0_LSB;
      global b1_MSB;
      global b1_LSB;
      global b2_MSB;
      global b2_LSB;
      global c12_MSB;
      global c12_LSB;

      a0_MSB = Pressure.bus.read_byte_data(Pressure.MPL115A2_ADDRESS,Pressure.MPL115A2_REGISTER_A0_COEFF_MSB+0);
      a0_LSB = Pressure.bus.read_byte_data(Pressure.MPL115A2_ADDRESS,Pressure.MPL115A2_REGISTER_A0_COEFF_LSB+0);

      b1_MSB = Pressure.bus.read_byte_data(Pressure.MPL115A2_ADDRESS,Pressure.MPL115A2_REGISTER_B1_COEFF_MSB+0);
      b1_LSB = Pressure.bus.read_byte_data(Pressure.MPL115A2_ADDRESS,Pressure.MPL115A2_REGISTER_B1_COEFF_LSB+0);

      b2_MSB = Pressure.bus.read_byte_data(Pressure.MPL115A2_ADDRESS,Pressure.MPL115A2_REGISTER_B2_COEFF_MSB+0);
      b2_LSB = Pressure.bus.read_byte_data(Pressure.MPL115A2_ADDRESS,Pressure.MPL115A2_REGISTER_B2_COEFF_LSB+0);

      c12_MSB = Pressure.bus.read_byte_data(Pressure.MPL115A2_ADDRESS,Pressure.MPL115A2_REGISTER_C12_COEFF_MSB+0);
      c12_LSB = Pressure.bus.read_byte_data(Pressure.MPL115A2_ADDRESS,Pressure.MPL115A2_REGISTER_C12_COEFF_LSB+0);

Solution

  • If it's OK for you that all the files are read one after the other, you can use a simple function.

    import time
    
    # ...
    
    def readCoefficients(self):
        global a0_MSB;
        global a0_LSB;
        global b1_MSB;
        global b1_LSB;
        global b2_MSB;
        global b2_LSB;
        global c12_MSB;
        global c12_LSB;
    
        max_retries = 15
    
        a0_MSB = self.readretry(Pressure.MPL115A2_REGISTER_A0_COEFF_MSB+0, max_retries)
        a0_LSB = self.readretry(Pressure.MPL115A2_REGISTER_A0_COEFF_LSB+0, max_retries)
    
        b1_MSB = self.readretry(Pressure.MPL115A2_REGISTER_B1_COEFF_MSB+0, max_retries)
        b1_LSB = self.readretry(Pressure.MPL115A2_REGISTER_B1_COEFF_LSB+0, max_retries)
    
        b2_MSB = self.readretry(Pressure.MPL115A2_REGISTER_B2_COEFF_MSB+0, max_retries)
        b2_LSB = self.readretry(Pressure.MPL115A2_REGISTER_B2_COEFF_LSB+0, max_retries)
    
        c12_MSB = self.readretry(Pressure.MPL115A2_REGISTER_C12_COEFF_MSB+0, max_retries)
        c12_LSB = self.readretry(Pressure.MPL115A2_REGISTER_C12_COEFF_LSB+0, max_retries)
    
        def readretry(self, address, max_retries):
            for i in range(max_retries):
                try:
                    return Pressure.bus.read_byte_data(
                        Pressure.MPL115A2_ADDRESS,
                        address
                    )
                except IOError as e:
                    # print(e)
                    time.sleep(0.1)
            else:
                raise IOError("Reading failed after multiple tries")
    

    Note: You should not use globals, most specially in classes.