It’s time to upgrade your code for Python3!

If you have been keeping up with Python news you will know that Python 2.x will not be supported in 2020 🙁 While it was the default install for many many years it’s time to get your scripts updated if you haven’t yet. As an example, here is how I modernized the ancient Robot Candy Thrower Code:

  1. Obvious exceptions – Run your code with “python3 <cmd>”, not “python <cmd>”, and you will certainly need to replace print “text” with print(“text”) and other obvious changes. If you had not been using “from __future__ import division” (and why wouldn’t you…) you may have changed division behavior due to the goofy integer division that was default in Python 2.x
  2. Install libraries needed – when I run “python3 ./faceDetectThreadCorrelationCV2FaceSmile.py” I got errors…
    ImportError: No module named ‘serial’
    ImportError: No module named ‘cv2’

    Looking up the modules to install opencv and python-serial for the usb arduino controller, I run
    pip3 install opencv-python
    pip3 install pyserial

    and the python3 interface for opencv gets installed. Repeat for other Import-errors that seem inexplicably missing.
  3. Library changes – perhaps it is OpenCV which rearranged constants and no longer needs “cv2.cv…” for referencing constants… or the unicode issue which turns .write(‘bytes’) to .write(str.encode(‘bytes’)). This level of error should usually have a well documented replacement for newly installed libraries.

Last but not least there was the original issue that I was going to fix… While the candy thrower was spinning, it would sometimes continue on while the arduino got unplugged. This hung the whole system. When this happens, you may see the /dev/ttyACM0, then reappear as /dev/ttyACM1… not great. When an error scrolls by among other errors that says:

/lib/python3.5/site-packages/serial/serialposix.py", line 571, in write
    raise SerialException('write failed: {}'.format(e))
serial.serialutil.SerialException: write failed: [Errno 5] Input/output error

it is not immediately obvious why that is happening and that the cause is a bumped usb cable… 🙂 especially when a bunch of warning messages print out after it! This is one of those things you may not immediately consider but needs to work in the real world of can-go-wrong=will-go-wrong… Whether it’s a usb device talking to an arduino over pyserial, or a network resource your code should handle all cases!

Instead of “while True:” I set it to while “os.path.exists(USBSERIAL):” and put a more sensible error message after the loop for when the usb is unplugged, also an exception handler that should give a hint as to what went wrong:

while os.path.exists(USBSERIAL):
  try:
     ...
  except serial.serialutil.SerialException:
            print("SerialException.")

print("It seems the usb device associated with %s is disconnected" % (USBSERIAL,))

Also note a better starting message in the code when the /dev/ttyACM0 does not exist or device is some different directory on your linux system.

Of course, if this were a production system we care about rather than a harvest festival candy thrower, Sentry or similar service would be a must have to integrate and immediately be alerted of new or reoccurring errors!

Leave a Reply

Your email address will not be published. Required fields are marked *

two × five =