Section 13.1. Dynamic Execution and the exec Statement


13.1. Dynamic Execution and the exec Statement

Python's exec statement can execute code that you read, generate, or otherwise obtain during a program's run. exec dynamically executes a statement or a suite of statements. exec is a simple keyword statement with the following syntax:

 exec code[ in globals [,locals]] 

code can be a string, an open file-like object, or a code object. globals and locals are dictionaries (in Python 2.4, locals can be any mapping, but globals must be specifically a dict; in Python 2.5, either or both can be any mapping). If both are present, they are the global and local namespaces in which code executes. If only globals is present, exec uses globals in the role of both namespaces. If neither globals nor locals is present, code executes in the current scope. Running exec in the current scope is a bad idea, since it can bind, rebind, or unbind any name. To keep things under control, use exec only with specific, explicit dictionaries.

13.1.1. Avoiding exec

Use exec only when it's really indispensable. Most often, it's best to avoid exec and choose more specific, well-controlled mechanisms instead: exec pries loose your control on your code's namespace, damages your program's performance, and exposes you to numerous, hard-to-find bugs.

For example, a frequently asked question about Python is "How do I set a variable whose name I just read or built?" Strictly speaking, exec lets you do this. For example, if the name of the variable you want to set is in varname, you might use:

 exec varname+'=23' 

Don't do this. An exec statement like this in current scope makes you lose control of your namespace, leading to bugs that are extremely hard to track, and more generally making your program unfathomably difficult to understand. An improvement is to keep the "variables" that you need to set not as variables, but as entries in a dictionary, say mydict. You can then use the following variation:

 exec varname+'=23' in mydict 

While this use is not as terrible as the previous example, it is still a bad idea. Keeping such "variables" as dictionary entries is simple and effective, but it also means that you don't need to use exec at all to set them. Just code:

 mydict[varname] = 23 

With this approach, your program is clearer, direct, elegant, and faster. While there are valid uses of exec, they are extremely rare and should always use explicit dictionaries.

13.1.2. Expressions

exec can execute an expression because any expression is also a valid statement (called an expression statement). However, Python ignores the value returned by an expression statement in this case. To evaluate an expression and obtain the expression's value, see built-in function eval, covered in eval on page 161.

13.1.3. Compile and Code Objects

To obtain a code object to use with exec, you normally call built-in function compile with the last argument set to 'exec' (as covered in "compile"). A code object c exposes many interesting read-only attributes whose names all start with 'co_', such as:


co_argcount

The number of parameters of the function of which c is the code (0 when c is not the code object of a function but rather is built directly by compile on a string)


co_code

A byte-string with c's bytecode


co_consts

The tuple of constants used in c


co_filename

The name of the file c was compiled from (the string that is the second argument to compile when c was built that way)


co_firstlinenumber

The initial line number (within the file named by co_filename) of the source code that was compiled to produce c if c was built by compilation from a file


co_name

The name of the function of which c is the code ('<module>' when c is not the code object of a function but rather is built directly by compile on a string)


co_names

The tuple of all identifiers used within c


co_varnames

The tuple of local variables' identifiers within c, starting with parameter names

Most of these attributes are useful only for debugging purposes, but some may help advanced introspection, as exemplified further on in this section.

If you start with a string that holds some statements, I recommend using compile on the string, then calling exec on the resulting code object rather than giving exec the string to compile and execute. This separation lets you check for syntax errors separately from evaluation-time errors. You can often arrange things so that the string is compiled once and the code object is executed repeatedly, which speeds things up. eval can also benefit from such separation. Moreover, the compile step is intrinsically safe (while both exec and eval are enormously risky if you execute them on code that you don't trust), and you may be able to perform some checks on the code object to lessen the risk.

A code object has a read-only attribute co_names, which is the tuple of the names used in the code. For example, say that you want the user to enter an expression that contains only literal constants and operatorsno function calls nor other names. Before evaluating the expression, you can check that the string the user entered satisfies these constraints:

 def safe_eval(s):     code = compile(s, '<user-entered string>', 'eval')     if code.co_names:         raise ValueError, ('No names (%r) allowed in expression (%r)' %                            (code.co_names, s))     return eval(code) 

This function safe_eval evaluates the expression passed in as argument s only if the string is a syntactically valid expression (otherwise, compile raises SyntaxError) and contains no names at all (otherwise, safe_eval explicitly raises ValueError).

Knowing what names the code is about to access may sometimes help you optimize the preparation of the dictionary that you need to pass to exec or eval as the namespace. Since you need to provide values only for those names, you may save work by not preparing other entries. For example, say that your application dynamically accepts code from the user with the convention that variable names starting with data_ refer to files residing in subdirectory data that user-written code doesn't need to read explicitly. User-written code may in turn compute and leave results in global variables with names starting with result_, which your application writes back as files in subdirectory data. Thanks to this convention, you may later move the data elsewhere (e.g., to BLOBs in a database instead of to files in a subdirectory), and user-written code won't be affected. Here's how you might implement these conventions efficiently:

 def exec_with_data(user_code_string):     user_code = compile(user_code_string, '<user code>', 'exec')     datadict = {  }     for name in user_code.co_names:         if name.startswith('data_'):             datafile = open('data/%s' % name[5:], 'rb')             datadict[name] = datafile.read( )             datafile.close( )     exec user_code in datadict     for name in datadict:         if name.startswith('result_'):             datafile = open('data/%s' % name[7:], 'wb')             datafile.write(datadict[name])             datafile.close( ) 

13.1.4. Never exec nor eval Untrusted Code

Note that function exec_with_data is not at all safe against untrusted code: if you pass it as argument user_code_string, which is some string obtained in a way that you cannot entirely trust, there is essentially no limit to the amount of damage it might do. This is unfortunately true of just about any use of both exec and eval, except for those rare cases in which you can set very strict and checkable limits on the code you're about to execute or evaluate, as was the case for function safe_eval.

Old versions of Python tried to supply tools to ameliorate this situation, under the heading of "restricted execution," but those tools were never entirely proof against the ingenuity of able hackers, and current versions of Python have therefore dropped them. If you need to ward against such attacks, take advantage of your operating system's protection mechanisms: run untrusted code in a separate process, with privileges as restricted as you can possibly make them (study the mechanisms that your OS supplies for the purpose, such as chroot, setuid, and jail). To ward against "denial of service" attacks, have the main process monitor the separate one and terminate it if and when resource consumption becomes excessive. Processes are covered in "Running Other Programs" on page 354.




Python in a Nutshell
Python in a Nutshell, Second Edition (In a Nutshell)
ISBN: 0596100469
EAN: 2147483647
Year: 2004
Pages: 192
Authors: Alex Martelli

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net