Loading functions from a file during run-time

TJ's Projects tjprojects_usenet at yahoo.com
Tue Feb 15 22:06:50 EST 2005


Answer below...

"Bryant Huang" <735115 at gmail.com> wrote in message news:<1108091598.055004.24890 at g14g2000cwa.googlegroups.com>...
> Hello!
> 
> I would like to read in files, during run-time, which contain plain
> Python function definitions, and then call those functions by their
> string name. In other words, I'd like to read in arbitrary files with
> function definitions, using a typical 'open()' call, but then have
> those functions available for use.
> 

<snip>

> 
> ===== [bar.txt] =====
> 
> def negate(x):
> 	return -x
> 
> def square(x):
> 	return x*x
> 
> 
> ===== [foo.py] =====
> 
> # open functions file
> foo_file = open("bar.txt")
> foo_lines = foo_file.readlines()
> foo_file.close()
> foo_str = "".join(foo_lines)
> 
> # compile code
> foo_code = compile(foo_str, "<string>", "exec")
> foo_ns = {}
> exec(foo_code) in foo_ns
> 
> # use functions
> k = 5
> print foo_ns["negate"](k)  // outputs -5
> print foo_ns["square"](k)  // outputs 25
> 
> 
> I'm not sure exactly what happens below the surface, but I'm guessing
> the 'compile()' and 'exec()' commands load in 'negate()' and 'square()'
> as functions in the global scope of 'foo.py'. I find that when I run
> 'compile()' and 'exec()' from within a function, say 'f()', the
> functions I read in from 'bar.txt' are no longer accessible since they
> are in global scope, and not in the scope of 'f()'.
> 
> Any pointers would be very welcome.
> 
> Thanks!
> Bryant

You're actually very close here.  The problem you are having is that
you are creating a local namespace (foo_ns) and executing that code
within that namespace.  To "import" the functions into the global
namespace, exec them as:

exec foo_code in globals()


You will then be able to call the methods as if they had been declared
locally, ie. 'negate(5)' rather than 'foo_ns["negate"](5)'.



<plug type="shameless">

I've written a simple line editor intended to be used within the
Python interactive interpreter, based on the old DOS 'edlin' command. 
This is how I enable the user to "import" the entered functions into
their local namespace.  The actual "execution" of the code is actually
pretty simple, and not much more involved than what you see here.  You
may be able to get some more ideas, however.

For more info (or comments, suggestions, or pointers), check out
http://pyedlin.sourceforge.net).

</plug>


Here's a simple example that shows a "good" input loop:

====== Start exec example ======
if __name__ == '__main__':
	funcdata = ['def func():\n', "\tprint 'Hello, world!'\n", '\n']

	codeline = ''
	for line in funcdata:
		codeline += line
		execline = codeline
		if execline.endswith('\n'):
			execline = execline[:-1]

		try:
			obj = compile(execline, '<string>', 'exec')
		except SyntaxError:
			pass
		else:
			exec obj in globals()
			codeline = ''

	func()

====== End exec sample ======


Executing this code will print 'Hello, world!' to the console.


Hope this helps!

T.J.



More information about the Python-list mailing list