eval() woes

R

rdrink

n.n.h. (noob needs help)
Ok, I've been beating my head against this for a day... time to ask
others.
To explain things as simply as possible:
I am trying to use eval() to evaluate some simple equations, such as--
pow(AB,2)
pow(AB,2)+A
pow(A+B,2)
pow(A+B,2)+A
and so forth... for a variety of math operations (+,-,*) and a variety
of variables, all of which have been genrated by a script, written to
a .txt file., then recalled sequentially and passed to eval().

The variables (A,B,C,D) are generated elsewhere [Note: AB is a concat,
e.g. A=2,B=7,AB=27] , so both are passed into a function e.g.
def (equation, list):
A=list[0]
B=list[1]
...etc.
return eval(str(equation))
Where 'equation' is one of the above, selected from the "equations
file"

So here's the rub:
With the above examples everything works fine... up to the last
(pow(A+B,2)+A), then it bombs with:
ValueError: invalid literal for int(): -
And I have tried 'hard typing' the vars e.g. A=str(list[0]) and
A=int(str(list[0]))... which only leads to it breaking in the other
expressions.
I have also tried 'compile()', which bombs the same way, and have also
looked at 'pickle' (but I don't think I really need to go that far)...

All of which leaves me wondering... Could it simply be that eval()
can't handle the progressive order of math operations? Because
pow(AB,2) + A works, as does pow(A+B,2)... but then adding pow(A+B,2)+A
(the result, *plus* A) doesn't?
Or is the problem deeper (like at the dictionary level)?

Either way I'm stumped, and could use some help.
Thanks
Robb Drinkwater
 
S

Simon Forman

rdrink said:
n.n.h. (noob needs help)
Ok, I've been beating my head against this for a day... time to ask
others.
To explain things as simply as possible:
I am trying to use eval() to evaluate some simple equations, such as--
pow(AB,2)
pow(AB,2)+A
pow(A+B,2)
pow(A+B,2)+A
and so forth... for a variety of math operations (+,-,*) and a variety
of variables, all of which have been genrated by a script, written to
a .txt file., then recalled sequentially and passed to eval().

The variables (A,B,C,D) are generated elsewhere [Note: AB is a concat,
e.g. A=2,B=7,AB=27] , so both are passed into a function e.g.
def (equation, list):
A=list[0]
B=list[1]
...etc.
return eval(str(equation))
Where 'equation' is one of the above, selected from the "equations
file"

So here's the rub:
With the above examples everything works fine... up to the last
(pow(A+B,2)+A), then it bombs with:
ValueError: invalid literal for int(): -
And I have tried 'hard typing' the vars e.g. A=str(list[0]) and
A=int(str(list[0]))... which only leads to it breaking in the other
expressions.
I have also tried 'compile()', which bombs the same way, and have also
looked at 'pickle' (but I don't think I really need to go that far)...

All of which leaves me wondering... Could it simply be that eval()
can't handle the progressive order of math operations? Because
pow(AB,2) + A works, as does pow(A+B,2)... but then adding pow(A+B,2)+A
(the result, *plus* A) doesn't?
Or is the problem deeper (like at the dictionary level)?

Either way I'm stumped, and could use some help.
Thanks
Robb Drinkwater

You must be doing something weird, that equation works for me:

|>> A, B = 2, 7
|>> eq = 'pow(A + B, 2) + A'
|>> eval(eq)
83

Try posting the minimal code example that causes the error and the
full, exact traceback that you get. (Or even just post the full
traceback that you're getting now, it would probably contain enough
information itself to solve your problem. And it's a good idea to do
that anyway, post the whole traceback, not just the final line.)

(Also, assuming your equations are already strings, there's no reason
to call str() on them again. And you mention a "dictionary level" but
don't mention using a dict.)

FWIW, the error "ValueError: invalid literal for int()" occurs when
you, uh, pass an invalid literal to the int() function (actually int
type.. but not important here), and includes the invalid input so you
don't have to guess at it:

|>> int('wombat')

Traceback (most recent call last):
File "<stdin>", line 1, in ?
int('wombat')
ValueError: invalid literal for int(): wombat

So, from what's visible in your post, it looks like int is getting
passed a bare '-', i.e. at some point you're calling int('-')...

HTH


Peace,
~Simon
 
R

rdrink

Hey Simon, Thanks for the reply.

Simon said:
You must be doing something weird, that equation works for me:
Try posting the minimal code example that causes the error and the
full, exact traceback that you get.

I appreciate the offer... but at this point my code is too recursive
and deeply nested to send a "simple" example
(Also, assuming your equations are already strings, there's no reason
to call str() on them again.

This is an interesting point: I AM putting them into the file as
strings, and then pulling them back out as such and you are right, they
do not need to be re-cast as strings. I think as some point I was
getting errors there, but for now I can omit that....
And you mention a "dictionary level" but
don't mention using a dict.)

Sorry, that was a spurious thought... No I'm not using a dict (although
I am still not sure if I should be)...
FWIW, the error "ValueError: invalid literal for int()" occurs when
you, uh, pass an invalid literal to the int() function (actually int
type.. but not important here), and includes the invalid input so you
don't have to guess at it:

|>> int('wombat')
HTH

Yes that is helpful.
I am still getting errors... which leads me to belive that it all has
to do with how I am casting, and re-casting, things as strings and
ints.
I need a little more time to try to suss this all out; after which, if
I still can't get it to work, I'll post some more code.

Thanks again for your thoughts and comments.

Robb
 
R

rdrink

Ok, maybe now I can make some more sense of this, with an example of
real code (sorry if it's a bit dense):
This is the basic function...

def equate(parts,new_eq):

oL = int(parts[0])
iL = int(parts[1])
iR = int(parts[2])
oR = int(parts[3])
oLoL = int(str(oL)+str(oL))
oLiL = int(str(oL)+str(iL))
oLiR = int(str(oL)+str(iR))
oLoR = int(str(oL)+str(oR))
iLoL = int(str(iL)+str(oL))
iLiL = int(str(iL)+str(iL))
iLiR = int(str(iL)+str(iR))
iLoR = int(str(iL)+str(oR))
iRoL = int(str(iR)+str(oL))
iRiL = int(str(iR)+str(iL))
iRiR = int(str(iR)+str(iR))
iRoR = int(str(iR)+str(oR))
oRoL = int(str(oR)+str(oL))
oRiL = int(str(oR)+str(iL))
oRiR = int(str(oR)+str(iR))
oRoR = int(str(oR)+str(oR))

new_seed = eval(new_eq)
return new_seed

.... into which is passed two items:
- 'parts' , which is a list e.g ['12','34','56','78'] (of strings)
- and 'new_eq',which is also a string read from a text file, e.g.
"pow(oLiL,2)"

And so...for the first 9 entries (of 480) in the text file where...
pow(oLiL,2)
pow(oLiL,2) - oL
pow(oLiL,2) - iL
pow(oLiL,2) - iR
pow(oLiL,2) - oR
pow(oLiL,2) + oL
pow(oLiL,2) + iL
pow(oLiL,2) + iR
pow(oLiL,2) + oR
pow(oLiL,2)
pow(oL - iL,2)
.... eval() works fine.
But on the 10th...
pow(oL - iL,2) - oL
.... it bombs with the error:
pow(oL - iL,2) - oL
Traceback (most recent call last):
File "the_farmer2.py", line 264, in ?
seed = equate(parts,equation)
File "the_farmer2.py", line 112, in equate
iL = int(parts[1])
ValueError: invalid literal for int(): -

And what is interseting/odd is:
- For the third, '- iL' evaluates fine...
- as well as the 9th, [where it is nested, oL - iL, inside pow()] ...
- but in the 10th, where a subtraction is called twice, it doesn't.
Which leads me to believe that the problem is either inside eval() it's
self, or in the way these variables are being cast... but I can't tell
which.

(BTW, as a footnote: For each of the above 'equations' the function
equate() was called 500 times... in some cases with the list 'parts'
equaling things like ['0',2','3','0'], so I have no reason to believe
that the problem is with the way the list is being passed in... but I
could be wrong)

Can anyone see something I can't?

Robb
 
J

John McMonagle

(BTW, as a footnote: For each of the above 'equations' the function
equate() was called 500 times... in some cases with the list 'parts'
equaling things like ['0',2','3','0'], so I have no reason to believe
that the problem is with the way the list is being passed in... but I
could be wrong)

Can anyone see something I can't?

Why don't you simply "print parts" as the first statement of your equate
function to check what its value is. Then work out where in your code
parts is being modified (especially parts[1]).

Regards,

John
 
S

Simon Forman

rdrink said:
Hey Simon, Thanks for the reply.



I appreciate the offer... but at this point my code is too recursive
and deeply nested to send a "simple" example

That's not an offer, it's a request. There's not enough information in
your original post to know what you're doing, let alone what you're
doing wrong.

If you explain for fully what's actually going on (i.e. tracebacks and
code) then it's much more likely that I or someone else on this list
will be able to help you figure out what's wrong.
 
G

Gabriel Genellina

File "the_farmer2.py", line 112, in equate
iL = int(parts[1])
ValueError: invalid literal for int(): -

So parts[1] is '-'.
Try adding a few print statements; I'd add a try/except around those
lines, printing parts, I bet it's not what you expect it to be.
The problem appears to be in the calling code, not on this function.
equate() was called 500 times... in some cases with the list 'parts'
equaling things like ['0',2','3','0'], so I have no reason to believe
that the problem is with the way the list is being passed in... but I
could be wrong)

....like above, where you missed a quote.
Can anyone see something I can't?

Not on the code fragment you posted.


Gabriel Genellina
Softlab SRL





__________________________________________________
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!
http://www.yahoo.com.ar/respuestas
 
S

Simon Forman

rdrink said:
Ok, maybe now I can make some more sense of this, with an example of
real code (sorry if it's a bit dense):
This is the basic function...

def equate(parts,new_eq):

oL = int(parts[0])
iL = int(parts[1])
iR = int(parts[2])
oR = int(parts[3])
oLoL = int(str(oL)+str(oL))
oLiL = int(str(oL)+str(iL))
oLiR = int(str(oL)+str(iR))
oLoR = int(str(oL)+str(oR))
iLoL = int(str(iL)+str(oL))
iLiL = int(str(iL)+str(iL))
iLiR = int(str(iL)+str(iR))
iLoR = int(str(iL)+str(oR))
iRoL = int(str(iR)+str(oL))
iRiL = int(str(iR)+str(iL))
iRiR = int(str(iR)+str(iR))
iRoR = int(str(iR)+str(oR))
oRoL = int(str(oR)+str(oL))
oRiL = int(str(oR)+str(iL))
oRiR = int(str(oR)+str(iR))
oRoR = int(str(oR)+str(oR))

new_seed = eval(new_eq)
return new_seed

... into which is passed two items:
- 'parts' , which is a list e.g ['12','34','56','78'] (of strings)

That's a lot of calls to str() to change the parts of parts *back* into
strings after changing them into ints. Why don't you just say
something like:

soL, siL, siR, soR = parts
oL, iL, iR, oR = map(int, parts)
oLoL = int(soL + soL)
oLiL = int(soL + siL)
..
..
..
etc...
?

If you're calling this function as many times as you indicate below
(just under a quarter of a million(!) if I understand you correctly,
480*500 = 240,000) , it might even result in a human-noticeable speed
up. ;-)
- and 'new_eq',which is also a string read from a text file, e.g.
"pow(oLiL,2)"

And so...for the first 9 entries (of 480) in the text file where...
pow(oLiL,2)
pow(oLiL,2) - oL
pow(oLiL,2) - iL
pow(oLiL,2) - iR
pow(oLiL,2) - oR
pow(oLiL,2) + oL
pow(oLiL,2) + iL
pow(oLiL,2) + iR
pow(oLiL,2) + oR
pow(oLiL,2)
pow(oL - iL,2)
... eval() works fine.
But on the 10th...
pow(oL - iL,2) - oL
... it bombs with the error:
pow(oL - iL,2) - oL
Traceback (most recent call last):
File "the_farmer2.py", line 264, in ?
seed = equate(parts,equation)
File "the_farmer2.py", line 112, in equate
iL = int(parts[1])
ValueError: invalid literal for int(): -

Ok, so there you go. At this point in the program parts[1] is '-',
which isn't an int literal, so the script raises an exception. One
very good thing to do here, as others have already mentioned, would be
to "print parts" at the beginning of your equate() function. That way
you could see exactly which data are causing the problem.
And what is interseting/odd is:
- For the third, '- iL' evaluates fine...
- as well as the 9th, [where it is nested, oL - iL, inside pow()] ...
- but in the 10th, where a subtraction is called twice, it doesn't.

None of this has anything to do with the error you posted. You're not
even getting as far as calling eval() or pow().

If you read the traceback carefully, starting at the last line in it
and working backwards, you'll see that you're calling int() with an
invalid literal '-', and that this occurs on line 112, in file
"the_farmer2.py", in the equate() function. The traceback even
presents you with a copy of the line in question: "iL = int(parts[1])"
so you know where the '-' is coming from. It's coming from parts[1].
Which leads me to believe that the problem is either inside eval() it's
self, or in the way these variables are being cast... but I can't tell
which.

The traceback tells you, unambiguously, that it's the latter, the
variable cast. That's *why* tracebacks exist, and why python prints
them by default: to tell you as much as it can about exactly what went
wrong.
(BTW, as a footnote: For each of the above 'equations' the function
equate() was called 500 times... in some cases with the list 'parts'
equaling things like ['0',2','3','0'], so I have no reason to believe
that the problem is with the way the list is being passed in... but I
could be wrong)

Can anyone see something I can't?

Learn to read tracebacks. They're your friends.

Peace,
~Simon
 
R

rdrink

Thanks everyone for you thoughtful replies...

And yes Simon you are right... I do need to learn how to read
'tracebacks' (and de-bugging tools in general)... but you are the first
person to give me a step-by-step explination, thank you.

And LOL you all caught my dropped single-quote ;-) ....
but unfortunately that was just a typo, not generated by my code.

And Simon thanks for this....
That's a lot of calls to str() to change the parts of parts *back* into
strings after changing them into ints. Why don't you just say
something like:

soL, siL, siR, soR = parts
oL, iL, iR, oR = map(int, parts)
oLoL = int(soL + soL)
oLiL = int(soL + siL)
.
.
.
etc...
?

.... I've never used mapping before, so this will be a good start.
If you're calling this function as many times as you indicate below
(just under a quarter of a million(!) if I understand you correctly,
480*500 = 240,000) , it might even result in a human-noticeable speed
up. ;-)

Oh it get's worse that that... it'll be (possibly) up to 500 times per
equation, for 334 equations, for 480 'seed numbers'... 500 * 334 * 480
= 80,327,000 calculations =:-o
So every little speed up helps!

----
Ok, so there you go. At this point in the program parts[1] is '-',
which isn't an int literal, so the script raises an exception. One
very good thing to do here, as others have already mentioned, would be
to "print parts" at the beginning of your equate() function. That way
you could see exactly which data are causing the problem.

Ok guys I'm not such a noob I didn't try that ;-)
but unfortunately it didn't enlighten anything.
However, as Simon points out...
None of this has anything to do with the error you posted. You're not
even getting as far as calling eval() or pow().
The traceback tells you, unambiguously, that it's the latter, the
variable cast.

the one thing I didn't mention (in trying to spare everyone having to
read *all* my code) is that the above mentioned list 'parts' of which I
am trying to use parts[1] etc, is passed in from another function...
and though I have gone over it repaetedly, looking for possible sources
of errors, Simons suggestion points to the problem originating there...
so I'll just have to keep looking.

Unfortunately I am going to have to put this project* away for a while
now, so let me just thank everyone again for helping a newcomer (I hope
someday I can return the favor) and let's retire this thread.

* BTW If any of you are interested in details of the project it's self
feel free to email me.

Thanks again!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top