我想按如下方式解析 Python 文档字符串:
Summary of class that is multiple lines.
Parameters
----------
param1 : str
Param 1 is a param
Returns
-------
value : str
Examples
--------
>>> print()
映射到
{
'base': 'Summary of class that is multiple lines.',
'params': 'param1 : str\n\tParam 1 is a param',
'returns': 'value : str',
'examples': '>>> print()'
}
这对于命名组和 re.match.groupdict
来说非常简单,但我遇到的问题是这四个组中的每一个都是可选的。这里有几个关于可选组的问题,特别是 https://stackoverflow.com/questions/27711175/regex-with-multiple-optional-groups 似乎相关,但这有很好的结尾字符来分解。此文档字符串可以包含任何字符(当前使用 [\s\S]
)。
回答1
我认为这应该有效:
^(?P<base>[\s\S]+?)??(?:(?:^|\n\n)Parameters\n-{10}\n(?P<params>[\s\S]*?))?(?:(?:^|\n\n)Returns\n-{7}\n(?P<returns>[\s\S]*?))?(?:(?:^|\n\n)Examples\n-{8}\n(?P<examples>[\s\S]*))?$
我用来生成这个 regex 的代码:
import re
sep_regex = r"(?:^|\n\n)"
summary_regex = r"(?P<base>[\s\S]+?)"
param_regex = rf"(?:{sep_regex}Parameters\n-{{10}}\n(?P<params>[\s\S]*?))"
returns_regex = rf"(?:{sep_regex}Returns\n-{{7}}\n(?P<returns>[\s\S]*?))"
examples_regex = rf"(?:{sep_regex}Examples\n-{{8}}\n(?P<examples>[\s\S]*))"
combined_regex = rf"^{summary_regex}??{param_regex}?{returns_regex}?{examples_regex}?$"
print(combined_regex)
例子:
from pprint import pprint
match = re.search(combined_regex, text) # text being your example text
pprint(match.groupdict())
# out: {'base': 'Summary of class that is multiple lines.',
# out: 'examples': '>>> print()',
# out: 'params': 'param1 : str\n Param 1 is a param',
# out: 'returns': 'value : str'}
我还使用删除的文档字符串的各个部分对其进行了测试。
回答2
您可以使用现有的库来解析文档字符串,而不是编写自己的正则表达式,其作者已经为您完成了艰苦的工作。
我使用 https://pypi.org/project/docstring-parser/ 包整理了一个示例。要安装此软件包,您需要运行以下命令:
pip install docstring-parser
然后您可以使用以下代码来解析您的文档字符串:
from docstring_parser import parse
docstring_text = """Summary of class that is multiple lines.
Parameters
----------
param1 : str
Param 1 is a param
Returns
-------
value : str
Examples
--------
>>> print()
"""
docstring = parse(docstring_text)
docstring_info = {
"base": docstring.short_description,
"params": [
{
"name": param.arg_name,
"type": param.type_name,
"description": param.description,
}
for param in docstring.params
],
"returns": {
"name": docstring.returns.return_name,
"type": docstring.returns.type_name,
}
if docstring.returns
else {},
"examples": [{"snippet": example.snippet} for example in docstring.examples],
}
print(docstring_info)
这给出了以下输出(为清楚起见添加了缩进):
{
"base": "Summary of class that is multiple lines.",
"params": [{"name": "param1", "type": "str", "description": "Param 1 is a param"}],
"returns": {"name": "value", "type": "str"},
"examples": [{"snippet": ">>> print()"}],
}