8

I use python with Pyserial to use the serial port, the code like this:

import serial
portName = 'COM5'

ser = serial.Serial(port=portName)

# Use the serial port...

But, the problem is, if the port is already open (by another application for example), I get an error when I try to open it like: "SerialException: could not open port 'COM5': WindowsError(5, 'Access is denied.')".

And I would like to know if I can open the port before trying to open it to avoid this error. I would like to use a kind of condition and open it only if I can:

import serial
portName = 'COM5'

if portIsUsable(portName):
    ser = serial.Serial(port=portName)

# Use the serial port...

EDIT:

I have found a way to do it:

import serial
from serial import SerialException

portName = 'COM5'

try:
    ser = serial.Serial(port=portName)
except SerialException:
    print 'port already open'

# Use the serial port...
Alain
  • 380
  • 1
  • 5
  • 15
  • 1
    Just do `try: your opening of port except YourError: pass` – sshashank124 Jun 30 '14 at 15:14
  • 1
    Just use a `try..except` block and catch the exception. Otherwise you would introduce a potential [race condition](http://stackoverflow.com/questions/14574518/how-does-using-the-try-statement-avoid-a-race-condition). – Lukas Graf Jun 30 '14 at 15:14
  • I tried to use try..except like this: `try: ser = serial.Serial(port=portName) except ValueError: pass` But I get also an error in the python console and I wan't to avoid it. – Alain Jun 30 '14 at 15:16
  • Why are you trying to catch a `ValueError` when the actual excption that's being raised is a `SerialException`? Use `try..except SerialException` (and import `SerialException` from the appropriate location beforehand). – Lukas Graf Jun 30 '14 at 15:19
  • just catch it all ... who cares why it didnt work the only important thing is that it didnt work ... if it didnt work for any reason, then it is notUsable ... – Joran Beasley Jun 30 '14 at 15:26
  • @user3771487 the way you do it in your edited post is exactly the way to do it. You can add a `sys.exit(1)` after `print 'port already open'` to prevent the rest of your code from getting executed and indicate an error by returning an exit code != 0. – Lukas Graf Jun 30 '14 at 17:08

1 Answers1

3
def portIsUsable(portName):
    try:
       ser = serial.Serial(port=portName)
       return True
    except:
       return False

as mentioned in the comments watch out for race conditions under circumstances where you are opening and closing alot ...

also it might be better to just return the serial object or None

def getSerialOrNone(port):
    try:
       return serial.Serial(port)
    except:
       return None

[edit] I intentionally left the except as a catch-all, because I posit that the actual failure does not matter. as regardless of the error, that port is not usable ... since the function is testing the usability of a port, it does not matter why you get an exception it only matters that you got an exception.

Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • 4
    Hmm, wouldn't it be better to `except SerialException:`? – Fred Larson Jun 30 '14 at 15:24
  • 1
    why? the definition of the function is isPortUsable ... who cares why it fails ... if it fails for any reason then it is by definition not usable ... `isPortUsable("GARBAGE") == False` even though "Garbage" will raise an IOError(at least i think ... maybe I should check) (nm it still raises serial exception ... but I still stand by the statement : "It doesnt matter why it fails, only that it fails" ... in this instance) – Joran Beasley Jun 30 '14 at 15:27
  • 3
    I'm wary of catch-all exception handlers in general. They swallow too much information, which leads to long debugging sessions. Neither function you've given here really adds any value. They just deprive you of the benefits of exceptions. – Fred Larson Jun 30 '14 at 16:45
  • @JoranBeasley I'm afraid you're re-introducing the OPs bad pattern in your first example. The point in using `try..except` to avoid a race condition is to **avoid** a check like `portIsUsable()` - if you just stick a `try..except` in such a function and then do an `if portIsUsable()` you've got just as much of a race condition as if you did the same thing without `try..except`. – Lukas Graf Jun 30 '14 at 17:01
  • 2
    Regarding the bare `except`: It's bad because it doesn't allow the user (or developer using a library) to distingish between exceptions that the original developer *excepected* (handled in some way) and unexpected ones. You simply swallow all of them like this, and suppress meaningful information (Permission denied? Already in use? No such port?). – Lukas Graf Jun 30 '14 at 17:04
  • 1
    How this would be solved without using a bare except – Yorfrank Bastidas Aug 03 '20 at 03:09