在自定义的python解释器中,如果运行单个命令,我可以看到命令输出 但是,如果我将命令放入文件并使用execfile运行(' file.py'),除了print命令,我什么都看不到。调试很难 使用execfile命令运行时如何检查命令输出?
尝试以下命令确认python版本。
import sys
print sys.version_info[0],sys.version_info[1]
2 7
答案 0 :(得分:2)
'命令输出'实际上不是一个有效的术语。 Python交互式解释器将回显任何expression statement的结果,除非该表达式生成None
。表达式语句是模块体中的顶级语句,它只包含一个表达式(而不是other simple statements such as assignment or import
或compound statements such as if
or while
。来自链接文档:
在交互模式下,如果值不是
None
,则使用内置的repr()
函数将其转换为字符串,并将结果字符串写入标准输出[...]一条线。 (不会写入产生None
的表达式语句,因此过程调用不会导致任何输出。)
在脚本中这样做是不切实际的;如果没有脚本用户必须解密打印到屏幕上的每个小东西,你将永远无法运行任何表达式语句。脚本通常希望控制打印的内容(根本不打印任何内容,例如使用日志记录)。
如果您使用execfile()
来运行脚本,则可以切换到将脚本解析为abstract syntax tree,此时您可以转换表达式语句节点以添加打印。生成的转换AST可以直接提供给compile()
函数,exec()
函数可以获取编译步骤的输出。
我在这里使用传递给exec()
的额外全局函数:
import ast
class ExprStatementPrinter(ast.NodeTransformer):
def visit_Expr(self, node): # expression statement node
# call the function __print_expr_result__, passing in the expression
# contents; replace the original expression contents with that call.
new_value = ast.Call(
ast.Name('__print_expr_result__', ast.Load()), # load as a global
[node.value], [], None, None) # node.value is the only argument
# to be able to execute, we need to set the lineno and coll_offset; just
# reuse the values of the expr node, then fix up any children
node.value = ast.copy_location(new_value, node.value)
return ast.fix_missing_locations(node)
def print_expr_result(result):
if result is not None:
print repr(result)
def execfile(filename):
with open(filename) as source:
tree = ast.parse(source.read())
ExprStatementPrinter().visit(tree) # updates the tree in-place
codeobj = compile(tree, filename, 'exec')
exec(codeobj, {'__print_expr_result__': print_expr_result})
我使用double-underscore 'system' defined name作为打印功能,以避免与脚本可能定义的任何内容发生冲突。
演示:
>>> example = '''\
... import sys
... sys.version_info[0],sys.version_info[1]
... 'Hello world!'
... None # should not be printed
... '''
>>> exec(example) # no output
>>> tree = ast.parse(example)
>>> ExprStatementPrinter().visit(tree)
<_ast.Module object at 0x1024c14d0>
>>> codeobj = compile(tree, '', 'exec')
>>> exec(codeobj, {'__print_expr_result__': print_expr_result})
(2, 7)
'Hello world!'
注意:这仅适用于您执行的顶级文件。任何导入的模块仍将在没有转换的情况下运行(就像它们在Python交互式解释器中一样)。您必须挂钩__import__
全局来拦截正常的导入机制。