我正在尝试处理一个在 Python 中操作另一个脚本的脚本,要修改的脚本具有如下结构:
class SomethingRecord(Record):
description = 'This records something'
author = 'john smith'
我使用 ast
来定位 description
行号,并使用一些代码根据行号将原始文件更改为新的描述字符串。到目前为止一切顺利。
现在唯一的问题是 description
偶尔是多行字符串,例如
description = ('line 1'
'line 2'
'line 3')
或
description = 'line 1' \
'line 2' \
'line 3'
我只有第一行的行号,没有以下行。所以我的单行替换器会做
description = 'new value'
'line 2' \
'line 3'
并且代码被破坏了。我想如果我知道 description
分配的开始行和结束/行数,我可以修复我的代码来处理这种情况。如何使用 Python 标准库获取此类信息?
最佳答案
我查看了其他答案;当您真正的问题是修改代码之一时,似乎人们正在做后空翻来解决计算行号的问题。这表明基准机制并没有以您真正需要的方式帮助您。
如果您使用 program transformation system (PTS) ,你可以避免很多这样的废话。
一个好的 PTS 会将您的源代码解析为 AST,然后让您应用源代码级别的重写规则来修改 AST,并最终将修改后的 AST 转换回源文本。通常 PTS 接受基本上这种形式的转换规则:
if you see *this*, replace it by *that*
[构建 AST 的解析器不是 PTS。他们不允许这样的规则;您可以编写临时代码来破解树,但这通常很尴尬。他们不使用 AST 来重新生成源文本。]
(我的 PTS,参见 bio,称为)DMS 是可以完成此任务的 PTS。使用以下重写规则可以轻松完成 OP 的具体示例:
source domain Python; -- tell DMS the syntax of pattern left hand sides
target domain Python; -- tell DMS the syntax of pattern right hand sides
rule replace_description(e: expression): statement -> statement =
" description = \e "
->
" description = ('line 1'
'line 2'
'line 3')";
一个转换规则被赋予一个名称replace_description,以将它与我们可能定义的所有其他规则区分开来。规则参数(e:表达式)表示该模式将允许源语言定义的任意表达式。 statement->statement 表示规则将源语言中的语句映射到目标语言中的语句;我们可以使用提供给 DMS 的 Python 语法中的任何其他语法类别。这里使用的"是一个元引用,用来区分规则语言的语法和主题语言的语法。第二个->将源模式 this 与目标模式 that 分开。
您会注意到没有必要提及行号。 PTS 通过使用用于解析源文件的相同解析器实际解析模式,将规则表面语法转换为相应的 AST。为模式生成的 AST 用于实现模式匹配/替换。因为这是由 AST 驱动的,所以原始代码的实际布局(间距、换行符、注释)不会影响 DMS 的匹配或替换能力。注释不是匹配的问题,因为它们附加到树节点而不是树节点;它们被保存在转换后的程序中。 DMS 确实捕获所有树元素的行和精确列信息;只是不需要实现转换。 DMS 也使用该行/列信息将代码布局保留在输出中。
其他 PTS 提供大致相似的功能。
关于python - 如何在 Python ast 中获取 "end-of-statement"的 lineno,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39779538/