Hi group, Question: Do eval() and exec not accept a function definition? (like 'def foo: pass) ?
I wrote a function to generate other functions using something like eval("def foo: ....") but it gave a syntax error ("Invalid syntax") with caret pointing to the 'd' of the def keyword. Details (sorry for the slight long post but thought it better to give more details in this case - wording is pretty clear, though, I think, so shouldn't take long to read): While working on a personal project for creating a server for a certain protocol (which I may make into an open source project later if it turns out to be any good), I wrote some simple functions to generate HTML start and end tags like <html>, <body>, </html>, </ body>, etc. - just to simplify/shorten my code a little. (I'm aware that there are HTML generation libraries out there, but don't think I need the overhead, since my needs are very simple, and anyway wanted to roll my own just for fun. For a bigger/more serious project I would probably use the existing libraries after doing a proper evaluation). So, this question is not about HTML generation but about Python's eval() function and exec statement. Started by writing functions like this: def start_html(): return '<html>\r\n' def end_html(): return '</html>\r\n' ... and similarly for the 'body', 'p', etc. HTML tags. (I used '\r\n' at the end because the server will send this output to the browser over HTTP, so that my code conforms to Internet protocols, and also so that while debugging, my output would have only one tag per line, for readability. Not showing the '\r\n in the rest of the code below) Then I realized that all these functions are very similar - only differ in the return value of the tag. So (being interested in metaprogramming of late), thought of writing a function that would generate these functions, when passed the appropriate tag name argument. [ Digression: I could of course have used another simple approach such as this: def start_tag(tag_name): return '<' + tag_name + '>' # called like this: # print start_tag('html') # print start_tag('body') # and def end_tag(tag_name): return '</' + tag_name + '>' # called like this: # print end_tag('body') # print end_tag('html') # and called similarly for the other HTML tags. While the above would work, it still would involve a bit more typing than I'd like to do, since I'[d have to pass in the tag name as an argument each time. I'd prefer having functions that I could call like this: print start_html() # which would print "<html>" print start_body() # which would print "<body>" # and so on ... just to make the code a little shorter and more readable. End of Digression] So, I wrote this code generation function: # AAAA import string def generate_html_tag_function(tag_name, start_or_end): start_or_end.lower() assert(start_or_end in ('start', 'end')) if start_or_end == 'start': func_def = "def start_" + tag_name + ":()\n" + \ "return '<' + tag_name + '>' else: func_def = "def end_" + tag_name + ":()\n" + \ "return '</' + tag_name + '>' function = eval(func_def) return function # meant to be called like this: start_html = generate_html_tag_function('html', 'start') start_body = generate_html_tag_function('body', 'start') end_html = generate_html_tag_function('html', 'end') end_body = generate_html_tag_function('body', 'end') # and the generated functions would be called like this: print start_html() print start_body() print end_body() print end_html() # BBBB # giving the output: <html> <body> </body> </html> But when I ran the above code (between the lines marked #AAAA and #BBBB), I got an error "Invalid syntax" with the caret pointing at the "d" of the def statement. I had used eval a few times earlier for somewhat similar uses, so thought this would work. I then looked up the Python Language Reference help, and saw that eval is used to evaluate Python expressions, not statements, and def is a statement. So looked up the exec statement of Python and saw that its syntax seemed to allow what I wanted. So replaced the line containing eval in the above with: exec(func_def) But that too gave the same error (I think so - I tried this yesterday and forgot to save the error messages, sorry about that, so can't be sure, but do think this was the case - if not, I'll save the exact code and output/errors later and repost here - not at my PC right now.) Thanks for any suggestions, Vasudev Ram Bize site: http://www.dancingbison.com PDF creation / conversion toolkit: http://sourceforge.net/projects/xtopdf Blog on software innovation: http://jugad.livejournal.com -- http://mail.python.org/mailman/listinfo/python-list