Reputation: 131677
So I have understood what exec
and eval
and also compile
do. But why would I need to use them? I am being unclear on the usage scenario.
Can anyone give me some examples so that I can better appreciate the concept. Cause right I know it is all theory.
Upvotes: 8
Views: 4643
Reputation: 736
I think I have a valid use. I am using Python 3.2.1 inside Blender 2.6.4 to modify a set of points with x,y coordinates (in the z-plane).
The goal is to add concentric rings of new points around each existing point, with the rings behaving as ripples, (like when you drop a stone in a pond). The catch is that I want the ripples to constructively/destructively interfere with one another, so first I'm going through and constructing a 'ripple equation' centered at each point, and summing all the ripple equations together into one gigantic mathematical equation, which I will then feed the original points into in order to generate the correct z-value to assign each one to.
My plan is to append each additional term in the equation to the previous as a string, and then use eval() to calculate the z-value for the new set of points.
Upvotes: 1
Reputation: 17500
I'll give an example in which I have used eval
and where I think it was the best choice.
I was writing a simple software testing utility ... something to test whether student exercises were conforming to the assignment requirements. The goal was to provide a way for a simple configuration file to serve as a test specification (to get around a "chicken-and-egg" issue of using a programming language to describe/document/implement the test cases for elementary programming assignments).
I based my harness on the ConfigParser in the standard libraries. However, I did want the ability to represent arbitrary Python strings (including interpolations of \n, \t, and especially any interpolated hex encoded ASCII characters in the values read therefrom.
My solution was a try
around an parsed_string=eval('''%s''' % cfg_read_item)
followed by a try
of the triple double-quoted version ("""%s""") of the same.
This is a case where the alternative would have been to write (or find a pre-written) Python language parser and figure out how to include and adapt it to my program. The risks are minimal (I'm not worried that student submitted code is going to trick my parser, break out if its jail, delete all my files, send my credit card numbers to Romania and so on)*
*(In part because I was testing them under Linux from an untrusted headless user account).
As here others have said, there are other use cases where you're building code from a template based on input data and need to execute that code (meta programming). You should always be able to accomplish those tasks in another way. However, whenever that alternative entails coding effort that approaches writing a general programming language parser/compiler/interpreter .... then eval
may be the better approach.
Upvotes: 5
Reputation: 123662
ast
uses compile
to generate abstract syntax trees from Python source code. These are used by modules such as pyflakes
to parse and validate Python.
def parse(expr, filename='<unknown>', mode='exec'):
"""
Parse an expression into an AST node.
Equivalent to compile(expr, filename, mode, PyCF_ONLY_AST).
"""
return compile(expr, filename, mode, PyCF_ONLY_AST)
Upvotes: 3
Reputation: 6441
Here's a valid use case. In the python paste middleware (for web programming) when an exception is raised it creates a command line within the browser. This works be using methods like these. Also, in Blender there is an option to animate values using python expressions and this works using eval.
Upvotes: 0
Reputation: 879691
The standard library has an instructive example of how to use exec
. collections.namedtuple uses it to build a class dynamically.
template = '''class %(typename)s(tuple):
'%(typename)s(%(argtxt)s)' \n
__slots__ = () \n
_fields = %(field_names)r \n
def __new__(_cls, %(argtxt)s):
'Create new instance of %(typename)s(%(argtxt)s)'
return _tuple.__new__(_cls, (%(argtxt)s)) \n
...'''
namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
OrderedDict=OrderedDict, _property=property, _tuple=tuple)
try:
exec template in namespace
except SyntaxError, e:
raise SyntaxError(e.message + ':\n' + template)
Upvotes: 4
Reputation: 9591
You don't need to use them, and in my opinion you should avoid them.
They are only useful in cases where you are generating the code itself, which in the end is going to most likely be considered bad practice.
If you are considering using eval() for things like mathematical expressions, you would be better sanitizing the input before evaluating it. You never know what kind of 'text' the user sends in that might screw up the application itself.
Upvotes: 2
Reputation: 1016
This is used in meta-programming (when the program writes itself). For example, you have animals of different species, which are described with different classes: Lion, Tiger, Horse, Donkey. And you want to simulate crossbreeding between them, for exampe, between Lion and Tiger. When you write the program, you can not determine how the user will cross the animals, but you can create new classes of animals on the fly:
new_class_name = boy.class.to_str() + girl.class.to_str()
eval("class " + new_class_name + " extends " + boy.class.to_str() + ", " + girl.class.to_str())
P. S. Sorry, I forgot Python some. So there is a bunch of pseudo-code.
Upvotes: 0
Reputation: 1467
Are you just asking for an example? You could write a simple app that reads from standard in and allows the user to input various expressions, like (4*2)/8 - 1
. In other languages (Java, C++, etc.) this would be close to impossible to evaluate, but in python it is simple, just:
eval((4*2)/8 - 1)
That being said, unless you are careful, using these things can be very dangerous as they (essentially)allow the user a huge amount of access.
Upvotes: 0