exec将始终返回None.从documentation:
exec(object[, globals[, locals]])
This function supports dynamic
execution of Python code. object must be either a string or a code
object. If it is a string, the string is parsed as a suite of Python
statements which is then executed (unless a syntax error occurs). [1]
If it is a code object, it is simply executed. In all cases, the code
that’s executed is expected to be valid as file input (see the section
“File input” in the Reference Manual). Be aware that the return and
yield statements may not be used outside of function definitions even
within the context of code passed to the exec() function. The return
value is None.
这是一个相当奇怪的要求.但你可以像这样捕获输出:
>>> s = """The number {% (c) print(x) %} is a random number between 1 and 6
... inclusive. If we multiply it by 2, we get {% (d) print(2*x) %}.
...
... What's interesting is that the statements may appear out of order in the
... document. {% (a) import random %} Thus I might generate the random
... number in a location in the document well after referencing it.
... {% (b) x = random.randint(1,6) %}"""
>>> import re
>>> stmts = re.findall(r'{%\s*\((\w*)\)\s*(.*)%}',s)
>>> stmts
[('c', 'print(x) '), ('d', 'print(2*x) '), ('a', 'import random '), ('b', 'x = random.randint(1,6) ')]
现在,您必须将输出重定向到某些可以在以后操作的流:
>>> import io
>>> import sys
>>> stream = io.StringIO()
>>> stdout = sys.stdout # this keeps stdout so we can set it back
>>> sys.stdout = stream
>>> for _, statement in sorted(stmts):
... exec(statement)
...
>>> sys.stdout = stdout # remember to reset stdout!
现在,您可以获得打印的值:
>>> stream.getvalue()
'5\n10\n'
>>> stream.getvalue().split()
['5', '10']
虽然,我认为更简单的方法是将命名空间传递给dict:
>>> namespace = {}
>>> for _, statement in sorted(stmts):
... exec(statement, namespace)
...
5
10
>>> namespace.keys()
dict_keys(['__builtins__', 'random', 'x'])
命名空间将加载正常的__builtins__,除非您自己提供.因此,要在执行的代码中创建每个名称,您可以找到namspace.keys dictview和包含字符串“__builtins__”的集合之间的区别.
>>> namespace.keys()
dict_keys(['__builtins__', 'random', 'x'])
>>> vals = namespace.keys() - {'__builtins__'}
>>> vals
{'random', 'x'}
>>> for val in vals:
... print(namespace[val])
...
5
>>>
虽然,如果您使用的是python 3.4> =将stdout重定向到某个流更容易:
>>> import contextlib
>>> stream = io.StringIO()
>>> with contextlib.redirect_stdout(stream):
... for _, statement in stmts:
... exec(statement)
...
>>> stream.getvalue()
'5\n10\n'
>>> stream.getvalue().split()
['5', '10']