Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
验证任意Python代码_Python_Python 2.7 - Fatal编程技术网

验证任意Python代码

验证任意Python代码,python,python-2.7,Python,Python 2.7,我有一个应用程序,它将接受一个字符串,然后将其作为任意python代码运行。我希望在尝试运行该字符串之前验证该字符串,并对其进行一些评估: 语法正确(这可以通过编译(stringCode,foo.py,“execute”)内置完成) 所有进口产品都可在当地购买 任意代码字符串中的类是否从特定类继承 来自#3的类是否也实现了一个特定命名的方法(这样我以后就可以对任意代码调用foo.bar()) 我已经查看了代码对象,但它们似乎无法执行任何操作,除非我尝试直接运行代码,而我更希望事先验证它是否有效您

我有一个应用程序,它将接受一个字符串,然后将其作为任意python代码运行。我希望在尝试运行该字符串之前验证该字符串,并对其进行一些评估:

  • 语法正确(这可以通过
    编译(stringCode,foo.py,“execute”)
    内置完成)
  • 所有进口产品都可在当地购买
  • 任意代码字符串中的类是否从特定类继承
  • 来自#3的类是否也实现了一个特定命名的方法(这样我以后就可以对任意代码调用
    foo.bar()

  • 我已经查看了代码对象,但它们似乎无法执行任何操作,除非我尝试直接运行代码,而我更希望事先验证它是否有效

    您可以使用
    ast.parse
    创建字符串的语法树。然后,您可以在树上迭代并验证您喜欢的任何解析时间质量

    正如互联网用户所说,这不会告诉您代码的运行时质量;如果模块是通过通常的
    import
    语句以外的机制导入的,则不会验证这些模块。如果您的类被动态地更改为添加或删除方法,那么仅通过查看类定义中的
    defs
    就不会知道这一点

    如果您不担心这些,下面是一个示例实现:

    import ast
    import sys
    import os
    import imp
    
    s = """
    import math, gzip
    from os import system
    import numpy
    import obviouslyFakeModuleName
    
    class A(int):
        def troz(self):
            return 23
    
    class B(str):
        def zort(self):
            return 42
    """
    
    def can_be_imported(name):
        try:
            imp.find_module(name)
            return True
        except ImportError:
            return False
    
    def iter_nodes_by_type(code, type_or_types):
        for node in ast.walk(code):
            if isinstance(node, type_or_types):
                yield node
    
    def iter_imported_module_names(code):
        for node in iter_nodes_by_type(code, ast.Import):
            for alias in node.names:
                yield alias.name
        for node in iter_nodes_by_type(code, ast.ImportFrom):
            yield node.module
    
    def iter_globally_defined_classes(code):
        for child in ast.iter_child_nodes(code):
            if isinstance(child, ast.ClassDef):
                yield child
    
    def iter_methods(class_):
        for node in ast.iter_child_nodes(class_):
            if isinstance(node, ast.FunctionDef):
                yield node
    
    try:
        code = ast.parse(s)
    except SyntaxError:
        print("That string is not valid Python.")
        sys.exit(0)
    
    #inspection of imports
    for name in iter_imported_module_names(code):
        if can_be_imported(name):
            print("module {} is available for import.".format(name))
        else:
            print("module {} is not available for import.".format(name))
    
    #inspection of classes
    for class_ in iter_globally_defined_classes(code):
        class_name = class_.name
        base_class_names = [name.id for name in class_.bases]
        function_names = [func.name for func in iter_methods(class_)]
        print("Inspecting class {}...".format(class_name))
        #we want to know if this class inherits directly from int
        if "int" in base_class_names:
            print("  Does inherit from int.")
        else:
            print("  Does not inherit from int.")
    
        #and does it implement zort()?
        if "zort" in function_names:
            print("  Implements `zort`.")
        else:
            print("  Does not implement `zort`.")
    
    结果:

    module math is available for import.
    module gzip is available for import.
    module numpy is not available for import.
    module obviouslyFakeModuleName is not available for import.
    module os is available for import.
    Inspecting class A...
      Does inherit from int.
      Does not implement `zort`.
    Inspecting class B...
      Does not inherit from int.
      Implements `zort`.
    

    如果不运行代码,这真的很难。类可以动态地创建和重新定义,停止的问题也在其中。是的,我想这会很粗糙。老实说,我只是想在这方面比在程序字符串中搜索“import*”然后尝试导入更聪明。如果用户想在创建类时变得怪异,那么他们可以自己解决这个问题。我只是想做一个健全的检查,确保我们有明显的模块可用,如果他们试图导入一些奇怪的东西,请发出警报。哇。哇。这看起来很完美。我一定要读一些语法树。它们看起来正是我想要处理的。我会等着看是否有其他人给出答案,但这看起来很棒。