472,968 Members | 1,803 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,968 software developers and data experts.

Do eval() and exec not accept a function definition? (like 'def foo: pass) ?


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

Jun 23 '07 #1
6 3582
MC
Hi!

Try with change all '\r\n' by '\n'

--
@-salutations

Michel Claveau
Jun 23 '07 #2
Hey,

I think you could use lambda functions for that matter (Ever heard of
them?). You could write something like:

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':
function = lambda: '<' + tag_name + '>'
else:
function = lambda: '</' + tag_name + '>'
return function

Then you would create the functions using the same code you had
written before:

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')
That seems to do what you want.

Eduardo

Jun 23 '07 #3
On Jun 24, 1:20 am, Eduardo Dobay <edudo...@gmail.comwrote:
Hey,

I think you could use lambda functions for that matter (Ever heard of
them?). You could write something like:

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':
function = lambda: '<' + tag_name + '>'
else:
function = lambda: '</' + tag_name + '>'
return function

Then you would create the functions using the same code you had
written before:

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')

That seems to do what you want.

Eduardo
Thanks to all the repliers.

@Eduardo: Yep, I had heard of lambdas, but didn't think to use them
here.
Will try this out - thanks!

- Vasudev
Jun 23 '07 #4
vasudevram wrote:
Hi group,

Question: Do eval() and exec not accept a function definition? (like
'def foo: pass) ?
def is the first keyword in a _statement_, not an expression.

exec executes statements, eval evaluates expressions.

try this:

exec "def foolish(x):\n y= x * 2\n print x, y"
foolish(2.4)
--
--Scott David Daniels
sc***********@acm.org
Jun 23 '07 #5
On Sat, 23 Jun 2007 19:58:32 +0000, vasudevram wrote:
>
Hi group,

Question: Do eval() and exec not accept a function definition? (like
'def foo: pass) ?
eval() is a function, and it only evaluates EXPRESSIONS, not code blocks.

eval("2+3") # works
eval("x - 4") # works, if x exists
eval("print x") # doesn't work

exec is a statement, and it executes entire code blocks, including
function definitions, but don't use it. Seriously.

ESPECIALLY don't use it if you are exec'ing data collected from untrusted
users, e.g. from a web form.

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.
You don't need eval or exec to write a function that generates other
functions. What you need is the factory-function design pattern:
def factory(arg):
def func(x):
return x + arg
return func

And here it is in action:
>>plus_one = factory(1)
plus_two = factory(2)
plus_one(5)
6
>>plus_two(5)
7

--
Steven.

Jun 24 '07 #6
On Jun 24, 6:28 am, Jean-Paul Calderone <exar...@divmod.comwrote:
On Sun, 24 Jun 2007 11:17:40 +1000, Steven D'Aprano <s...@remove.this.cybersource.com.auwrote:
On Sat, 23 Jun 2007 19:58:32 +0000, vasudevram wrote:
Hi group,
Question: Do eval() and exec not accept a function definition? (like
'def foo: pass) ?
eval() is a function, and it only evaluates EXPRESSIONS, not code blocks.

Actually, that's not exactly true:
>>x = compile('def foo():\n\tprint "hi"\n', '<stdin>', 'exec')
>>l = {}
>>eval(x, l)
>>l['foo']()
hi
>>>

Jean-Paul
Thanks, all. Will check out the replies given.
- Vasudev

Jun 24 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Jean-Sébastien Bolduc | last post by:
Hello, I would like to associate a local namespace with a lambda function. To be more specific, here is exactly what I would want: def foo(): a = 1 f = lambda x : a*x return f
1
by: Art | last post by:
Hello, I can't seem to get eval or compile to accept the print stmt, or any complicated statements. The documentation I've looked out doesn't explain why this is. ex: >>>...
1
by: Andr? Roberge | last post by:
I have the following two files: #--testexec.py-- def exec_code(co): try: exec co except: print "error" #-- test.py--
2
by: pasa | last post by:
I'm an old time python user, but just got bitten by namespaces in eval. If this is an old discussion somewhere, feel free to point me there. Based on the documentation, I would have expected the...
10
by: Julian Smith | last post by:
I've been playing with a function that creates an anonymous function by compiling a string parameter, and it seems to work pretty well: def fn( text): exec 'def foo' + text.strip() return foo ...
10
by: Antoon Pardon | last post by:
I have the following little piece of code: class Cfg:pass #config = Cfg() def assign(): setattr(config, 'Start' , ) def foo(): config = Cfg()
4
by: Michael | last post by:
Hi, I'm having difficulty finding any previous discussion on this -- I keep finding people either having problems calling os.exec(lepev), or with using python's exec statement. Neither of...
6
by: dave.g1234 | last post by:
Suppose I have a function in module X that calls eval e.g, X.py _______ Def foo(bar): Eval(bar) _______ Now eval will be called using the default eval(bar,globals(),locals()) and globals...
2
by: Danny Shevitz | last post by:
Howdy, In my app I need to exec user text that defines a function. I want this function to unpickle an object. Pickle breaks because it is looking for the object definition that isn't in the...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
3
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.