【问题标题】:Using python ast parser to process multi line strings使用python ast解析器处理多行字符串
【发布时间】:2022-06-27 04:00:34
【问题描述】:

当将 python AST 解析器模块与包含多行字符串的脚本结合使用时,这些多行字符串总是被简化为单行引号字符串。示例:

import ast

script = "text='''Line1\nLine2'''"

code = ast.parse (script, mode='exec')
print (ast.unparse (code))

node = code.body[0].value
print (node.lineno, node.end_lineno)

输出是:

> text = 'Line1\nLine2'
> 1 2

因此,尽管在解析之前是多行字符串,但在未解析时文本会减少为单行引号字符串。这使得脚本转换变得困难,因为在解析转换后的 AST 图时多行会丢失。

有没有办法用 AST 正确解析/反解析带有多行字符串的脚本?

提前谢谢你。

【问题讨论】:

  • 字符串文字的 Value 对象包含列号和行号,因此您可以从解析的文本中提取原始源字符串。但是,将它与 unparse() 的其余部分放在一起需要一些技巧。 (不过绝对可行。)
  • 是的,但这需要再次进行一些启发式方法,并且引用等将是一个手动问题。我仍然希望能够将此委托给 AST 对象。

标签: python parsing abstract-syntax-tree multiline quoting


【解决方案1】:

ast.unparse 的底层source 的检查表明,visit_Constant 方法的编写者_write_constant 将生成字符串repr,除非特别避免使用反斜杠过程:

class _Unparse:
   ...
   def _write_constant(self, value):
      if isinstance(value, (float, complex)):
          ...
      elif self._avoid_backslashes and isinstance(value, str):
          self._write_str_avoiding_backslashes(value)
      else:
          self.write(repr(value))

默认情况下,_avoid_backslashes 设置为 False,但是,如果字符串节点是多行,则可以通过覆盖 visit_Constant 并专门调用 _write_str_avoiding_backslashes 来正确执行多行字符串格式化:

import ast
class Unparser(ast._Unparser):
   def visit_Constant(self, node):
      if isinstance(node.value, str) and node.lineno < node.end_lineno:
         super()._write_str_avoiding_backslashes(node.value)
         return
      return super().visit_Constant(node)

def _unparse(ast_node):
   u = Unparser()
   return u.visit(ast_node)

script = "text='''Line1\nLine2'''"
print(_unparse(ast.parse(script)))

输出:

text = """Line1
Line2"""

【讨论】:

  • 哇,这是深刻的洞察力,确实有效。我可以基于此构建解决方案。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 2018-10-10
  • 2021-12-11
  • 2014-03-24
相关资源
最近更新 更多