Paul Lussier wrote:

>I'd like to see/hear others ideas on how to write this same script.
>I'm most interested in improvements or commentary on why what I did
>is either right, wrong, interesting, stupid, etc.


Below you'll find my stab at it -- it might not be correct, or even run, b/c I haven't 
actually got an /etc/group file to try it out on right now.  There's a couple "best 
practices" for Python that I've picked up over the past couple of years that I used, 
too:

1. Unless you're literally writing a one-shot throwaway script to do some task that 
you'll probably never do again, try to write your script as a set of functions or 
classes rather than a start-to-finish script.  This is because every Python script can 
be imported into any other Python script as a module (same can be done with Perl using 
a package declaration if I'm not mistaken) by using "import myscript" where the script 
file is named "myscript.py" and is located somewhere on your PYTHONPATH (an 
environment variable that tells the Python interpreter where to search for modules to 
import, that by default includes only the current working directory).

2. If you're doing the above, then the way you actually invoke your script is by 
providing a "main" method (or any other name you prefer).  Then, the only part of your 
script that is *not* located in a function or class definition is the line "if 
__name__ == '__main__': main()", which simply invokes the main() function you defined 
if the name of the magic __name__ variable is "__main__".  If you are invoking the 
script directly (rather than importing it into another script as a module), then this 
conditional test will prove true, and your main() function will be executed.

3. I read somewhere that a cool trick is setting the arguments of a Python script as 
the default arguments of main() if it is not passed any arguments explicitly.  The 
advantage of this is that, if you're debugging your script in the interactive 
interpreter, you can call the main() function on your script (by importing "myscript" 
and then calling "myscript.main()") and pass it a list of any arbitrary arguments you 
like.  If you pass arguments into main(), they will be used instead of sys.argv (which 
is good because in the interactive interpreter, there are no arguments in sys.argv).

4. I know that a class can be used as a struct in the way you were using, but I don't 
generally use it as such -- the reason I use Python is because it's very 
straightforward and easy to read, and I find that such a use of a Python class is a 
little un-obvious.  In fact, that technique is often used only to show how Python lets 
you dynamically create object attributes at runtime, though I have seen it used in 
real-life Python scripts too.  For my approach, I created a "Group" class in my 
version of your script, which of course you can now use in any Python script that 
imports your script by referencing it as "myscript.Group".  A dict is a more 
straightforward way to use a simple struct-like object, as Cole suggested.  The 
overhead of using a class over a dict is not very significant, though, since Python's 
classes are really just customized dict types behind the scenes.  But you don't need 
to know that.  And because dicts are used so extensively in Python, they are ultra-opt!
imized by the Python developers.  (Also, if performance is a big concern, then you can 
always write some of the code in C and then import it into your Python script as a 
module.)

5. I try to bundle up behavior that is specific to an object into the class that 
defines that object, rather than act upon the object from the outside.  I tried to do 
that here, by providing a "toLdifFormat()" method on the Group class.  The advantage 
to this is that it simplifies the code that's making use of the Group objects.  Also, 
returning a string from this method rather than printing it makes it more flexible, 
since you can always print it out later but maybe you wanted to write it to a file or 
a database -- in that case, having it in string format is handier.  Likewise, the 
constructor to the Group class lets you set the name, gid, and members manually 
(useful if you're debugging the script from the interactive interpreter, or perhaps if 
using Group from another script), but if you don't, it just sets them to empty 
strings.  In that case you can use the convenience method "setValuesFromLine" and pass 
in a line read from a /etc/groups file.  Again, this is Group-spec!
ific behavior so it's nice to stuff this code in with the Group class where it can be 
used anywhere the Group class is used.

Anyway, those are just some thoughts on how I implemented your same script in Python.  
In fact, most of my simpler Python scripts end up looking a lot like this -- they 
consist of one or more classes that define the objects in question, and then a simple 
main() function that actually performs the processing using these objects.  Although 
this is a little more verbose than your original script, you might find it a little 
easier to re-use in other scripts, too.

Good luck in studying Python!  Always glad to see this language in use.


Erik





#!/sw/bin/python

import os, sys


class Group:
    
    def __init__(self, name="", gid="", members=[]):
        self.name = name
        self.gid = gid
        self.members = members
        
    def setValuesFromFileLine(self, line):
        record = line.split(":")
        self.name = record[0]
        self.gid = record[2]
        self.members = record[3].split(",")
        
    def toLdifFormat(self):
        self.members.sort()
        output = ",".join(members)
        return "%s:%s:%s" % (self.name, self.gid, output)



def main(args=sys.argv):
    f = file(args[1], "r")
    groups = []
    
    for line in f:
        g = Group()
        g.setValuesFromFileLine(line)
        groups_dict[g.name] = g
    
    f.close()
    
    for group in groups:
        print group.toLdifFormat()


if __name__ == "__main__":
    main()



_______________________________________________
gnhlug-discuss mailing list
[EMAIL PROTECTED]
http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss

Reply via email to