D
David MacKay
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()
<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()