A clean way to program an interface

Paul McGuire ptmcg at austin.rr.com
Mon Jul 9 12:59:40 EDT 2007


I believe the OP is talking about "interface" as in "hardware
interface", using some form of serial communication.  His example does
not use pyserial, but it does refer to a "UnidenConnection" class,
with parameters such as bitrate, port, etc. for what looks like serial
communication.

Some general comments:

1. Much of the OP's use of sys._getframe().f_code.co_name coincides
with his naming of certain methods with the same name as the command
to be sent down the serial line.  "STS", "EPG", "PRG", "SIN", etc. are
all 3-character command codes that get sent down the wire, along with
the appropriate values for the particular command.  While many of
these routines have *some* code in common, only a few have their
entire method body duplicated with one or more other methods.
Refactoring a couple of these into code closures, you can get:

    @staticmethod
    def makeStatusCheckCommandFunction(cmd):
        def fn(self):
            return ( self.uniden.write(cmd)[0]=="OK" )
        return fn
    PRG = makeStatusCheckCommandFunction("PRG")
    EPG = makeStatusCheckCommandFunction("EPG")


    @staticmethod
    def makeCmdFunction(cmd,attrname):
        def fn(self):
            setattr(self, attrname, int(self.PRGWrite(cmd)[0]))
            return getattr(self,attrname)
        return fn
    SCT = makeCmdFunction("SCT","systems")
    SIH = makeCmdFunction("SIH","sih")
    SIT = makeCmdFunction("SIT","sit")

Now there is no sys._getframe().f_code.co_name legerdemain going on,
the command strings are just passed along as the argument cmd, and the
functions themselves are named the same for some level of self-
documentation and/or convenience.

For the remaining methods, I declare a local variable named cmd and
assign to it the write mnemonic.  Yes, I know it violates DRY ("Don't
Repeat Yourself"), but it avoids the getframe() stuff and again, is at
least a snippet of self-documentation.

2. This code for reading and unpacking all the non-blank values feels
ugly:

    cmd = "SIF"
    if args is None:
        p=self.PRGWrite("%s,%s" % (cmd,idx))
        t={}
        t["site_type"],t["name"],t["quick_key"],t["hld"],t["lout"],\
            t["mod"],t["att"],t["cch"],t["apco"],t["threshold"],\
            t["rev_index"],t["fwd_index"],t["sys_index"],t["chn_head"],
\
            t["chn_tail"],t["seq_no"],t["start_key"],t["latitude"],\
            t["longitude"],t["range"],t["gps_enable"],t["rsv"]=p

        delitems=[]
        for item in t:
            if t[item]=="": delitems.append(item)
        for x in delitems: del t[x]

How about this instead?:

    cmd = "SIF"
    if args is None:
        p=self.PRGWrite("%s,%s" % (cmd,idx))
        names = "site_type name quick_key hld lout mod att cch "\
                "apco threshold rev_index fwd_index sys_index "\
                "chn_head chn_tail seq_no start_key latitude " \
                "longitude range gps_enable rsv".split()

        t = dict( k,v for k,v in zip(names,p) if v != "" )


HTH,
-- Paul




More information about the Python-list mailing list