首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于散列Python函数的python函数

用于散列Python函数的python函数
EN

Code Review用户
提问于 2018-04-24 16:34:02
回答 1查看 443关注 0票数 5

我正在开发一种分布式构建系统。该系统允许作为构建步骤执行脚本片段。我需要能够以注释和文档字符串不影响散列的方式散列这些代码片段。通过使用ast模块解析代码,然后执行ast.dump并对结果字符串进行散列,我获得了部分进展。自然的下一步是清除每个FunctionDef节点正文中的第一个Expr(str())节点。

这是迄今为止我找到的最好的解决方案。

有没有更好的方法来解决这个问题?

代码语言:javascript
复制
import ast
import hashlib
import inspect

def _remove_docstring(node):
    '''
    Removes all the doc strings in a FunctionDef or ClassDef as node.
    Arguments:
        node (ast.FunctionDef or ast.ClassDef): The node whose docstrings to
            remove.
    '''
    if not (isinstance(node, ast.FunctionDef) or
            isinstance(node, ast.ClassDef)):
        return

    if len(node.body) != 0:
        docstr = node.body[0]
        if isinstance(docstr, ast.Expr) and isinstance(docstr.value, ast.Str):
            node.body.pop(0)

#-------------------------------------------------------------------------------
def hash_function(func):
    '''
    Produces a hash for the code in the given function.
    Arguments:
        func (types.FunctionObject): The function to produce a hash for
    '''
    func_str = inspect.getsource(func)
    module = ast.parse(func_str)

    assert len(module.body) == 1 and isinstance(module.body[0], ast.FunctionDef)

    # Clear function name so it doesn't affect the hash
    func_node = module.body[0]
    func_node.name = "" 

    # Clear all the doc strings
    for node in ast.walk(module):
        _remove_docstring(node)

    # Convert the ast to a string for hashing
    ast_str = ast.dump(module, annotate_fields=False)

    # Produce the hash
    fhash = hashlib.sha256(ast_str)
    result = fhash.hexdigest()
    return result

#-------------------------------------------------------------------------------
# Function 1
def test(blah):
    'This is a test'
    class Test(object):
        '''
        My test class
        '''
    print blah
    def sub_function(foo):
        '''arg'''
print hash_function(test)

#-------------------------------------------------------------------------------
# Function 2
def test2(blah):
    'This is a test'
    class Test(object):
        '''
        My test class
        '''
    print blah
    def sub_function(foo):
        '''arg meh'''
print hash_function(test2)
EN

回答 1

Code Review用户

发布于 2018-04-25 06:19:06

看一看ast.get_docstring的源代码,您的代码或多或少会做它所做的事情。这是他们的代码供参考:

代码语言:javascript
复制
def get_docstring(node, clean=True):
    """
    Return the docstring for the given node or None if no docstring can
    be found.  If the node provided does not have docstrings a TypeError
    will be raised.
    """
    if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)):
        raise TypeError("%r can't have docstrings" % node.__class__.__name__)
    if not(node.body and isinstance(node.body[0], Expr)):
        return
    node = node.body[0].value
    if isinstance(node, Str):
        text = node.s
    elif isinstance(node, Constant) and isinstance(node.value, str):
        text = node.value
    else:
        return
    if clean:
        import inspect
        text = inspect.cleandoc(text)
return text

他们提到的几件事仅仅是Python 3+的一个关注点,比如AsyncFunctionDef。而且,Constant似乎是Python 3+中引入的一种语法规则。(但是,您可能希望在将来考虑到这一点。)

您似乎也要从ClassDef中删除文档字符串,我不能百分之百地肯定,但是您也可能希望添加Module

还有一个ast.NodeTransformer。然而,与你目前的循环方法相比,我发现它在风格上相当怪异。所以..。我对你是否应该使用它没有信心。尽管如此,我把它放在那里,所以你是知道的,以防你没有。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/192848

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档