Answer below... "Bryant Huang" <[EMAIL PROTECTED]> wrote in message news:<[EMAIL PROTECTED]>... > 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. -- http://mail.python.org/mailman/listinfo/python-list