Converting from perl

C.Laurence Gonsalves clgonsal at
Sat Aug 28 23:15:59 CEST 1999

On Wed, 25 Aug 1999 00:43:01 GMT, sp00fD <sp00fD at> wrote:
> In article <m3ogfwrfwo.fsf at>,
>   Michael Hudson <mwh21 at> wrote:
> > sp00fD <sp00fD at> writes:
> >
> > To be honest, I don't see a lot of value in wrapping this up in a
> > class. For a straight through shell scripty type job like this I
> > generally don't bother. Python is not about ramming methodologies down
> > your throat.
> >
> Honestly, me neither, more than anything I wanted to get a feel for
> them, basically I was bound and determined to create a class, but when I
> was done, it was obviously stupid.  Unfortunately, most of the stuff I
> do is "straight through shell scripty" so, hopefully I can figure out
> some decent way to use the OO features of python for that.

Well, one thing I would probably avoid in a class is having any
references to "global" sorts of things like sys.argv. Classes are best
used to package reusable chunks of code. If you go and parse command
line arguments in the class, it's hard to use that class for anything
else. The other great thing about classes is polymorphism, but you
pretty well need more than one class to make that happen...

Since this particular chunk of code is almost entirely command line
argument parsing, I don't see how you can make use of classes in a very
effective way.

I do understand that you're doing this as a learning excercise though,
so to give you an idea of how OO might be useful for a very similar
problem to the one you have...

Suppose that some of your machines don't work with rcp. Suppose some
needed ssh, others FTP, others HTTP-put. Maybe in some of them you store
everything in a database, and you need to do sql statements. The end
user doesn't care. They just want to be able to say "get my file over
there". You could do something like this:

    import sys
    import os
    from ftplib import FTP

    class DestinationMachine:
        pass # sometimes I wish Python had abstract classes or interfaces...

    class RCPDestinationMachine(DesitinationMachine):
        def __init__( self, hostname ):
            self.hostname = hostname

        def copy( self, src, dest ):
            if os.system( "rcp %s %s:%s" % (src, self.hostname, dest) ):
                raise "Argh!" # this is pretty cheesy...

    class FTPDestinationMachine(DesitinationMachine):
        def __init__( self, hostname, userid, passwd ):
            self.hostname = hostname
            self._userid = userid
            self._passwd = passwd

        # warning: totally untested code ahead
        def copy( self, src, dest ):
            server = FTP( self.hostname, self._userid, self._passwd )
            fp = open(src)
            server.storbinary( "STOR " + dest, fpi, 4096 )

    # do the same for other copying mechanisms

Then you could make a map that maps server names to the appropriate
DestinationMachine object for that server. 

    tempMachineList = (
        RCPDestination( "frodo" ),
        RCPDestination( "bilbo" ),
        FTPDestination( "jupiter", "root",      "zeus" ),
        FTPDestination( "saturn",  "foofoo",    "barbar" ),
        FTPDestination( "mars",    "plaintext", "password" )
    hostMap = {}
    for host in tempMachineList:
        hostMap[host.hostname] = host
    del tempMachineList
    # now hostMap maps from hostnames to DestinationMachine objects

Your copy method (in your existing class) would then look something like:

        def copy(self):
                _stuff = self.files()

                        for hostname in self.get_hosts():
                                print "Sending %s to %s %s" % \
                                (_stuff[0], host, _stuff[1])
                                hostMap[hostname].copy( src, dest )
                        print "Error during copy - oops"

and it would automagically use rcp, ftp, or whatever machanism was
appropriate for the destination machine.

You could then also reuse these classes in other scripts that needed to
copy files between machines as part of their larger duties. You could
even put the code that creates the mapping and all of the
'DestinationMachine' objects into a module so that when you
get/find-out-about a new machine, all of your scripts will know about it.

  C. Laurence Gonsalves            "Any sufficiently advanced
  clgonsal at                 technology is indistinguishable  from magic." -- Arthur C. Clarke

More information about the Python-list mailing list