如何查看命令运行结果?

时间:2018-04-18 08:48:22

标签: python python-2.7

在自定义的python解释器中,如果运行单个命令,我可以看到命令输出 但是,如果我将命令放入文件并使用execfile运行(' file.py'),除了print命令,我什么都看不到。调试很难 使用execfile命令运行时如何检查命令输出?

尝试以下命令确认python版本。

import sys
print sys.version_info[0],sys.version_info[1]
2 7

1 个答案:

答案 0 :(得分:2)

'命令输出'实际上不是一个有效的术语。 Python交互式解释器将回显任何expression statement的结果,除非该表达式生成None。表达式语句是模块体中的顶级语句,它只包含一个表达式(而不是other simple statements such as assignment or importcompound 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__全局来拦截正常的导入机制。