使用正则表达式检测python函数?
我想取出python脚本中的所有python函数。我是否可以使用任何一个正则表达式来执行此操作,例如:使用正则表达式检测python函数?,python,regex,Python,Regex,我想取出python脚本中的所有python函数。我是否可以使用任何一个正则表达式来执行此操作,例如: import re all_functions = re.findall(regex, python_script) 我已经实现了一种非常麻烦的方法来实现这一点,它涉及许多if语句,但我觉得有一种更优雅的解决方案使用正则表达式 我认为正则表达式应该是这样的: 'def.*?\n\S' 因为: 函数以def开头 后面跟着任何东西(但我们不想贪婪) 当换行符\n之后的下一行的起始字符不是空格\
import re
all_functions = re.findall(regex, python_script)
我已经实现了一种非常麻烦的方法来实现这一点,它涉及许多if语句,但我觉得有一种更优雅的解决方案使用正则表达式
我认为正则表达式应该是这样的:
'def.*?\n\S'
因为:
\n
之后的下一行的起始字符不是空格\S
编辑:Python函数可能包含在没有扩展名
.py
的文件中;e、 g.它们可以包含在扩展名为.ipynb
的IPython笔记本中,因此我不必总是导入代码并使用dir()
不要使用正则表达式。让Python为您分析代码,并使用以下命令查找所有函数定义:
如果代码包含在.ipynb
文件中,则解析该文件并提取code
单元格,然后通过相同的过程从这些单元格中输入源代码
使用ast
模块源代码本身进行演示:
>>> import ast
>>> with open(ast.__file__.rstrip('c')) as sourcefile:
... tree = ast.parse(sourcefile.read(), sourcefile.name)
...
>>> for node in ast.walk(tree):
... if isinstance(node, ast.FunctionDef):
... print(node.name)
...
parse
literal_eval
dump
copy_location
fix_missing_locations
increment_lineno
iter_fields
iter_child_nodes
get_docstring
walk
_convert
_format
_fix
visit
generic_visit
generic_visit
这个正则表达式可能适合您:
re.compile('def(?p(?p.*)\(?p.*):')
我使用了组,因此您可以使用match对象的groupdict()方法轻松地获取信息,但是如果您只需要声明行,那么可以使用
re.compile('def.*?\(.*):')
这个正则表达式可以更紧一些(它可以接受def-do-something(1,2,3):
,即使它不是一个有效的函数),但是如果您的python文件在语法上是正确的,并且您绝对想使用正则表达式,这将为您完成这项工作。为什么不将它作为模块导入,通过dir
查看其内容并检查其类型?如果代码是可信的,当然要感谢您的建议,但我一直在寻找一种适用于所有文件类型的解决方案,例如,有时IPython笔记本中的python函数具有.ipynb扩展名,因此,正则表达式可以让我从这些文件类型中提取函数def
后面不能跟“任何东西”,这里有一个标识符的定义。也许你应该研究一下Python的语法?另外,如果您希望
包含所需的换行符re.DOTALL
.jornsharpe,您是对的,正则表达式应该更具体,可能类似于'def[A-Za-z_][A-Za-z_0-9]*?\(.?\)'
,假设文件中只包含编写良好的python函数,我认为应该检测函数的开头。“1.函数以def开头”。这几乎是完全错误的。它们可以分配给变量,从代码对象合成,用lambda
语句匿名构建,分配给globals()
字典中的键,或者在eval
抬起丑陋的头的任何地方都像魔术一样出现。。。我肯定我错过了一些。一般来说,您不能使用正则表达式来解析像Python这样的非正则语言。这是不可能的,除非是在非常有限的情况下。。。即使这样,也只有在您已经确切知道要查找什么的情况下。谢谢,ast库看起来很酷,我会尝试使用它。谢谢Akshay,但我正在尝试获取整个函数,而不仅仅是函数名,因此正则表达式需要以类似“\n\S”的形式终止,并且还需要匹配多行。
>>> import ast
>>> with open(ast.__file__.rstrip('c')) as sourcefile:
... tree = ast.parse(sourcefile.read(), sourcefile.name)
...
>>> for node in ast.walk(tree):
... if isinstance(node, ast.FunctionDef):
... print(node.name)
...
parse
literal_eval
dump
copy_location
fix_missing_locations
increment_lineno
iter_fields
iter_child_nodes
get_docstring
walk
_convert
_format
_fix
visit
generic_visit
generic_visit