#141 open: Pass errno from IOError to SerialException

v1.0 (example)
closed-fixed
Chris Liechti
None
5
2013-10-10
2013-01-14
Miro Hrončok
No

I've added errno to SerialException, so it is possible to read it when catching it in apps using pyserial.

Discussion

  • Miro Hrončok
    Miro Hrončok
    2013-01-14

    open: Pass errno from IOError to SerialException

     
    Attachments
  • Chris Liechti
    Chris Liechti
    2013-05-31

    is the patch incomplete? it just adds an argument to the exception, which would alter the output when the exception is printed.

    also this error number would not be portable across platforms, so a program relying on it would fail, e.g. on Windows.

     
  • Miro Hrončok
    Miro Hrončok
    2013-05-31

    Forgive me, if I've done anything wrong, but I believe I'm right.

    List of facts:

    • SerialException inherits from IOError
    • IOError provides an error number, that can be later systematically processed
    • SerialException is raised only when IOError was raised underneath (not sure, correct me)
    • SerialException only contains a string

    Therefor, it has no reason at all to inherit form IOError. If you want to inherit something, it should follow the rule of "is" - SerialException is an IOError. Is it? If so, it should contain an error number.

    If my imaginary app catches IOError, it except an error number. When SerialException is raised, it is caught (because it inherits from IOError), but no errno is there. I cannot tell the user politely, what wen't wrong and what should (s)he do. Only thing I can do, is to show the error message.

    except SerialException as e:
        # Currently, there is no errno, but it should be there in the future
        if e.errno == 2:
            print _("Error: You are trying to connect to a non-exisiting port.")
        elif e.errno == 8:
            print _("Error: You don't have permission to open %s.") % port
            print _("You might need to add yourself to the dialout group.")
        else:
            print e
    

    Passing errno to IOError or it's ancestors is not obligatory, of course, but the problem is: you have the number (from IOError) already. Why do you throw it away?

    About the cross platform incompatibility - I believe also on Windows there is a IOError error number, but the fact it, I might be wrong. If this is the case, basically just check if msg.errno exists and pass it along only if it does.

    try:
        raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
    except AttributeError:
        raise SerialException("could not open port %s: %s" % (self._port, msg))
    

    But I donẗ think this aproach will work, because as far as I know, IOError always has (at least an empty) errno:

    In [1]: ioe = IOError()
    
    In [2]: ioe.errno
    
    In [3]: ioe.blahblah
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-3-5b821a12d5ce> in <module>()
    ----> 1 ioe.blahblah
    
    AttributeError: 'exceptions.IOError' object has no attribute 'blahblah'
    

    Thanks

     
  • Chris Liechti
    Chris Liechti
    2013-10-10

    • status: open --> closed-fixed
    • assigned_to: Chris Liechti
    • Group: --> v1.0 (example)
     
  • Chris Liechti
    Chris Liechti
    2013-10-10

    OK, accepted, though that only adds that feature only for posix.

    Personally, I'd recommend against evaluating errno or trying to show very specific error messages as this is not possible in a simple, cross platform way, and the point of pySerial is, to some extent, that it's easy to run the same program on different platforms (at least on posix it would be easy to use the serial port directly).