pythonic equivalent of upvar?

David MacKay mackay at aims.ac.za
Tue Dec 20 15:10:30 CET 2005


Dear Greater Py,

<motivation note="reading this bit is optional">
     I am writing a command-line reader for python.

     I'm trying to write something with the same brevity 
as perl's one-liner

eval "\$$1=\$2" while @ARGV && $ARGV[0]=~ /^(\w+)=(.*)/ && shift;

and with similar functionality.  I've decided I don't like 
getopt, because it seems to require me to write pages and pages 
of elif's as I add new arguments.  It slows me down, whereas the 
perlism above liberates.

My solution is a twenty-line python chunk equivalent to the perl one-liner. 
(Twenty lines because, to process a (name, value) pair, I have to find the 
current type of the variable "name" before setting "name" to righttype("value").

I'm happy with this 20-line chunk and wish to re-use it in many python programs.
</motivation>

<question>
 What is the pythonic way to embed a 20-line chunk of code into a function?
I'd love to define these 20 lines as a module, and reuse the module over and over.
but this chunk of code needs to have access to 
the local variables of main, whatever they are called. 

 In tcl, IIRC, the command "upvar" allows one function to get access to its 
parent function's local variables.

 Is there a pythonic way to tell a function "you are allowed to see all your 
parent's variables?"  Or, to tell a chunk of code, "you are just a chunk of 
code, not really a function"?
</question>

Thanks very much

David

PS -- example below illustrates the chunk of code, in case anyone is interested.

#!/usr/bin/env python
"""
 This program commandline.py illustrates a command-line reader   (David MacKay, license: GPL)
 that works a little like perl's
        eval "\$$1=\$2" while @ARGV && $ARGV[0]=~ /^(\w+)=(.*)/ && shift;
 usage: (all arguments are optional)
        commandline.py -bits 5  -decode 1 -file pimple  -N 10000
"""
import sys
def usage(name):
    print "Usage: %s -variableName value" % name
    sys.exit()
    
def main():
    ## Define DEFAULTS that can be overridden on the command line
    decode=0    ## are we decoding?
    verbose=0   ## verbose output?
    bits=7      ## how big are the blocks? 
    N = 10000   ## What is the file length?
    file="blah" ## file name string
    ## End defaults

    ## Command-line reader:  Reads pairs of the form
    ##                     "    -variableName value        "
    ##                   and sets  variableName=value. Gives error if this syntax is violated.
    while ( len(sys.argv) > 1 ):
        if ( sys.argv[1][0] == "-" ):
            name = sys.argv.pop(1)
            name = name[1:len(name)] 
            if( len(sys.argv) <= 1 ): 
                print >> sys.stderr, "could not get value for name ", name
                usage(sys.argv[0])
            else:
                value = sys.argv.pop(1)
                # here, we should assert that this variable exists!
                command = "ntype = type(%s)" % (name)   # find type of this variable 
                exec command
                # convert value to the right type
                command = "%s = ntype(%s) # %s" % ( name,`value`, str(ntype) )
                if verbose:
                    print >> sys.stderr , "setting value:", command
                exec command
        else:
            usage(sys.argv[0])
    ## End of command-line reader

    ## defaults that cannot be overridden on command line
    securityLevel = 1
    ## end defaults

    ## Main program starts here
    
    print >> sys.stderr, "  N =",N,"  bits =",bits, \
          "   file = ",file,      "       decode = ", decode

if __name__ == '__main__':    main()



-- 
--
David J.C. MacKay     mackay at aims.ac.za     787 9336
                      http://www.aims.ac.za/~mackay/



More information about the Python-list mailing list