Serial Ports Context Manager
-
11-02-2021 - |
Question
Is the following a reasonable approach?
with SerialPorts() as serial_ports:
in= SerialPort("COM1")
serial_ports.add(in)
out = SerialPort("COM2")
serial_ports.add(out)
# use in and out
where SerialPorts
and SerialPort
implement the context manager interface.
SerialPorts.exit()
loops through the added serial ports calling their exit()
. SerialPort
's exit()
closes the serial port.
Is there a better way of doing this?
Solution
If you run this code:
class A(object):
def __enter__(self):
return self
def __exit__(self, *args):
print "exit", self
class B(object):
def __enter__(self):
return self
def __exit__(self, *args):
print "exit", self
raise Exception
with A() as a, B() as b:
pass
you will see that both __exit__
s get called even if one raises an error (with either A
before B
and B
before A
).
If you call both __exit__
s from a single collective __exit__
, if the first has an error the second __exit__
won't get called.
Use nested context managers instead, assuming you have a small fixed number of them.
OTHER TIPS
How about this?
with SerialPorts("COM1", "COM2") as (inport, outport):
# use inport and outport
in
is a reserved word in python, and using it as a variable name will result in a SyntaxError.
Edit: Here's one possible implementation (untested):
import serial
from contextlib import contextmanager
@contextmanager
def serial_ports(*args):
ports = [serial.Serial(arg) for arg in args]
try:
yield ports
finally:
for port in ports:
port.close()
with serial_ports('COM1', 'COM2') as (inp, outp):
print 'inp:', inp.isOpen(), 'outp:', outp.isOpen()
print 'inp:', inp.isOpen(), 'outp:', outp.isOpen()
But I defer to @agf on this one. His suggestion is much better for your case.