Welcome, guest | Sign In | My Account | Store | Cart

This is useful for making easy and human to write definition files for whatever use. For example, lets say you are writing a simulator and you need an easy, human way to define parts about a given world like light sources, obstacles, and dimensions. see the discussion for this example fleshed out in code.

Python, 13 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#parse a python file in a given environment, and get out some results
from os import dirname

def parseFile(filename, envin, envout = {}):
	exec "from sys import path" in envin
	exec "path.append(\"" + dirname(filename) + "\")" in envin
	envin.pop("path")
	lines = open(filename, 'r').read()
	exec lines in envin
	returndict = {}
	for key in envout:
		returndict[key] = envin[key]
	return returndict

For the example above, You might write something like the following:

from parsefile import parseFile

class World:

    def dimensions(self, width, height):
        self.width = width
        self.height = height

    def __init__(self, filename):
        self.lightsources = []
        self.obstacles = []
        envin = {}
        envin['dimensions'] = self.dimensions
        envin['newobstacle'] = lambda x,y: self.obstacles.append((x,y))
        envin['newlightsource'] = lambda x,y: self.lightsources.append((x,y))
        parseFile(filename, envin)

If you were to then call something like World(file) in the runtime of your program where file is as follows:

#

dimensions(4, 5) newlightsource(1, 2) newlightsource(2, 3) newobstacle(0, 1)

#

You will end up with an instance of class World with the appropriate data, thus it is simple to create new ways to specify data for your program

5 comments

N N 17 years, 9 months ago  # | flag

Oh my.

lines = open(filename, 'r').readlines()
total = ""
for line in lines:
    total += line

Is a rather long way to spell:

total=open(filename,'r').read()
Michael Haimes (author) 17 years, 8 months ago  # | flag

very true.. fortunately, it would only eat up a humanly unidentifiable amount of processor time unless the file was a ridiculous length. I made the change though

Ilan Copelyn 17 years, 7 months ago  # | flag

Can't get this example working. Sorry - I'm new to Python.

I get:-

    envin['dimensions'] = dimensions
NameError: global name 'dimensions' is not defined

And if i change the line so the function name "dimensions" is qualified by the class "World", then I get problems when trying to exec the text read from the file.txt:-

    exec lines in envin
  File "", line 2, in ?
TypeError: unbound method dimensions() must be called with World instance as first argument (got int instance instead)

BTW I'm using Python 2.4

Michael Haimes (author) 17 years, 7 months ago  # | flag

again, a typo on my end. It should have been self.dimensions instead of dimensions

the dimensions method is indeed a method of the class World, but Python doesn't have static methods like java. Plus, this method needs an instance of world in order to edit instance data like width and height.

the self keyword in Python is equivalent to the this keyword in Java, and just refers to the instance of the class that the method was called in.

Ilan Copelyn 17 years, 7 months ago  # | flag

Thanks. that did the trick cheers

Created by Michael Haimes on Wed, 26 Jul 2006 (PSF)
Python recipes (4591)
Michael Haimes's recipes (1)

Required Modules

Other Information and Tasks