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?

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top