【问题标题】:Parsing python file for all methods and classes解析所有方法和类的python文件
【发布时间】:2016-11-03 16:00:24
【问题描述】:

我正在尝试构建一个程序,允许用户浏览到包含 python 模块的文件夹。选择文件夹后,它将列出该文件夹中的所有 python 文件以及每个模块的所有类和方法。我的问题是,有什么方法可以在不打开每个文件并解析“def”或“class”的情况下做到这一点?我注意到有一个名为 mro 的函数,它返回一个类的属性,但这需要我通过导入访问该类。那么有什么办法可以得到相同的结果吗?提前谢谢!

【问题讨论】:

标签: python python-2.7


【解决方案1】:

这是我使用 AST 模块提出的,它正是我想要的。

def fillClassList(file):
    classList = []
    className = None
    mehotdName = None
    fileName = "C:\Transcriber\Framework\ctetest\RegressionTest\GeneralTest\\" + file
    fileObject = open(fileName,"r")
    text = fileObject.read()
    p = ast.parse(text)
    node = ast.NodeVisitor()
    for node in ast.walk(p):
        if isinstance(node, ast.FunctionDef) or isinstance(node, ast.ClassDef):
            if isinstance(node, ast.ClassDef):
                className = node.name
            else:
                methodName = node.name
            if className != None and methodName != None:
                subList = (methodName , className)
                classList.append(subList)
    return classList

【讨论】:

    【解决方案2】:

    如果你想知道文件的内容,没有办法查看文件:)

    您的选择取决于您是要自己解析出感兴趣的内容,还是要让 Python 加载文件然后询问它找到了什么。

    对于一个非常简单的 Python 文件,比如下面的 testme.py,你可以这样做(警告:不适合那些胃不好的人):

    testme.py:

    class Foo (object):
        pass
    
    def bar():
        pass 
    

    分析.py:

    import os.path
    
    files = ['testme.py']
    for f in files: 
        print f
        modname = os.path.splitext(f)[0]
        exec('import ' + modname)
        mod = eval(modname)
        for symbol in dir(mod):
            if symbol.startswith('__'):
                continue
            print '   ', symbol, type(eval(modname + '.' + symbol))
    

    输出:

    testme.py
       Foo <type 'type'>
       bar <type 'function'>
    

    但是,当您扩展它以处理嵌套的包和模块以及损坏的代码和等等等等时,这将开始变得非常糟糕。 grep class 和/或 def 可能更容易,然后从那里开始。

    玩得开心!我 :heart: 元编程

    【讨论】:

    • Python 有比“exec”和“eval”更好(并且更安全)的解决方案 - 如果您关心系统的安全性,那就是......
    • 我确实说过它不适合那些胃不好的人:)
    • “我如何点燃我的生日蜡烛?” “哦,这很简单,把自己点燃,然后把燃烧的手放在蛋糕上。警告:不适合那些胃虚弱的人。”说真的,这不是一个信息警告,当有这么多更好的解决方案时,你根本不应该建议execeval
    • importing 任意文件也很危险,它应该发出警告。不过,用更安全的替代品替换 import 并不是那么简单。)
    【解决方案3】:

    大部分 Python 的实现(包括解析器)都可以在 stdlib 中找到,所以仔细阅读 modules index 你应该会找到你需要的。首先想到的模块/包是importlibinspectast,但肯定还有其他感兴趣的模块。

    【讨论】:

    • @Ted 请在您的帖子中发布此代码(您可以编辑它) - 在评论中它只是不可读。
    • 我的错,我发布了它,但我需要等待 5 分钟才能更改它,我有点忘了它:P 但我已经在下面做了
    【解决方案4】:

    我不得不在我的一个模块中替换很多代码,这是我获取类和方法的方式:

    def listClass(file):
    
        with open(file,"r") as f:
            p = ast.parse(f.read())
    
        # get all classes from the given python file.
        classes = [c for c in ast.walk(p) if isinstance(c,ast.ClassDef)]
    
        out = dict()
        for x in classes:
            out[x.name] = [fun.name for fun in ast.walk(x) if isinstance(fun,ast.FunctionDef)]
    
        return out
    

    样本pprint 输出:

    {'Alert': ['__init__',
               'fg',
               'fg',
               'bg',
               'bg',
               'paintEvent',
               'drawBG',
               'drawAlert'],
     'AlertMouse': ['__init__', 'paintEvent', 'mouseMoveEvent'],
     'AlertPopup': ['__init__', 'mousePressEvent', 'keyPressEvent', 'systemInfo']}
    

    【讨论】:

      【解决方案5】:

      谢谢,这是第一次作为用户的有用示例。上面的代码带有导入、打印输出,并且没有 1 个拼写错误;-)

      import ast
      
      classList = []
      className = None
      methodName = None
      fileName = "C:\\fullPathToAPythonFile.py"
      fileObject = open(fileName ,"r")
      text = fileObject.read()
      p = ast.parse(text)
      node = ast.NodeVisitor()
      for node in ast.walk(p):
          if isinstance(node, ast.FunctionDef) or isinstance(node, ast.ClassDef):
              if isinstance(node, ast.ClassDef):
                  className = node.name
              else:
                  methodName = node.name
              if className != None and methodName != None:
                  subList = (methodName , className)
                  classList.append(subList)
                  print("class: " + className + ", method: " + methodName)
      

      【讨论】:

        猜你喜欢
        • 2012-05-28
        • 2011-06-02
        • 2016-11-11
        • 2020-04-09
        • 2018-05-18
        • 2018-12-31
        • 2019-05-10
        • 2019-03-05
        • 2021-12-05
        相关资源
        最近更新 更多