【问题标题】:How to embed a language like JSX into a python script?如何将 JSX 之类的语言嵌入到 python 脚本中?
【发布时间】:2019-10-27 01:44:20
【问题描述】:

在我们公司,我们喜欢编写 django 驱动的应用程序,我们也喜欢使用 react。最近我们考虑为 python 编写一个基于组件的模板引擎,其中模板可以使用 JSX 编写为类似反应的组件。

理想情况下,应该可以将 JSX 嵌入到 Python 代码中,这样您就可以编写如下组件:

header.pyx:

import PyReact
from my_awsome_project.components import Logo, Link


def Header(context):
    page_title = context.get('page_title')
    links = context.get('links')

    return (
        <div>
            <Logo /> 
            {page_title}
            <ul>
                {[<Link href={link.url}>{link.title}</Link> for link in links]}
            </ul>
        </div>
    )

这当然需要先转译文件以获得有效的 python 代码。它会转译成有点类似的东西:

import PyReact
from my_awsome_project.components import Logo, Link


def Header(context):
    page_title = context.get('page_title')
    links = context.get('links')

    return (
        PyReact.createComponent('div', context, [
            PyReact.createComponent(Logo),
            page_title,
            PyReact.createComponent('ul', context, [
                 [
                      PyReact.createComponent(Link, {'href': link.url}, link.title)
                      for link in links
                 ]
            ]),
        ])
    )

问题是:我将如何编写这样的转译器?

我们还考虑过,我们可以返回一个包含 JSX 的字符串,而不是直接将 JSX 直接嵌入到 Python 代码中,该字符串会被独立解析。那会是更好/更简单的方法吗?

【问题讨论】:

    标签: python parsing jsx interpreter template-engine


    【解决方案1】:

    我认为这对于 SO 来说基本上是一个过于宽泛的问题,任何答案都将在 SO 指导方针关于意见的边缘滑行。您实质上是在就复杂问题寻求设计建议,而 SO 并不是真正用于此目的。

    不过,这是一个有趣的问题。我会尝试解决这些问题,但不会过于深入地进行自以为是的设计(因为我对这个主题有自己的看法)。

    1. 转译是实用的,至少在理论上是这样,如果你能成功,它会给你带来合理的性能。

    2. 反复解析模板字符串让我觉得效率低下且复杂;复杂性与评估嵌入式 Python 代码有关,您需要在定义字符串文字的范围内执行此操作,这可能不是解析它的范围。

    3. JSX 风格的词法分析和解析并不是特别复杂,但是您假设的转译器还需要了解 Python 的词法和句法分析。 Python 的标准库包括用于对 Python 进行词法分析和解析的模块,但是它们不可扩展,这可能使其难以与嵌入式语言一起使用。您可以编写自己的词法分析器和解析器,可能使用您选择的代码生成器,或者您可以将您的词法分析器和解析器基于一些开源 Python 实现。在这两种情况下,您的可维护性挑战将是使您的自定义代码与未来的 Python 版本保持同步。

    4. 将伪 HTML 嵌入到另一种语言中的主要问题是检测 &lt; 何时是比较运算符以及何时启动模板。最简单的解决方案是,仅当 &lt; 被词法分析为一个完整的标记(因此 &lt;= 始终是一个运算符),后跟一个标识符,并且在一个表达式的句法环境中遇到时,才允许模板预计。

    5. 上面的最后一个要求是确保3 &lt; count(例如)不会使转译器误以为它即将看到&lt;count...&gt; 组件。我很确定在 Python 中您可以使用基于前面标记的简单词法规则,但需要进行完整的语法分析来验证

    6. 一旦你开始一个模板,它会一直持续到你到达匹配的结束标签;如果需要匹配标签,这非常简单。但它更适合自顶向下解析而不是自底向上解析,因为结束标签匹配是上下文相关的。如果你在词法分析和句法分析之间有密切的合作,这很容易做到,但这种合作有时会令人不悦:-)

    7. 由于嵌入在模板中的 Python 代码本身可以包含一个嵌入的模板,该模板又可以嵌入更多的 Python 代码等,因此您的分析需要递归。预期的递归深度不是很大,所以递归本身没有问题,但是许多解析器生成器并不能优雅地处理这种递归。我建议使用(或实现)与缓冲区处理程序分离的“推送解析器”和词法分析器框架,以便您可以轻松更改缓冲区中间的扫描仪。

    8. 缓冲区处理可以非常简单;最低要求只是一个字符串和该字符串的索引。如果您在缓冲区处理程序中隔离实现细节,您应该能够稍后更改为不同的实现,例如不需要在开始解析之前获得整个输入的实现。您可能实际上并不需要该功能,但维护独立组件总是好的,以防万一

    9. 转译器的另一个挑战是将其与 Python 的模块系统集成。 Pythonic 集成可能建议在导入模块时执行转译。另一方面,您可能希望能够分发预编译的包,无需安装转译器即可使用,并且不依赖于特定版本的转译器。如果你花一些时间思考这个问题,你可能会避免以后的问题。 (例如,Ply 问题使得无法将 Ply 项目捆绑到单文件分发系统中。)

    希望能有所帮助。

    【讨论】:

    • 你是绝对正确的。这个问题可以说超出了 SO 的范围。我希望它会被标记为诚实,因为我可能也这样做了:D 为我的双重标准感到羞耻。无论如何,我非常感谢你的回答。它有一些非常好的指针,我什至没有想过。这似乎不是我们能在一周内完成的事情。我想我会首先寻找一个可扩展的词法分析器/解析器。如果我们决定在生产环境中使用它,可维护性似乎是一个更大的问题。与 javascript 相比,关于该主题的阅读也很少。
    • @trixn:是的,一周会非常乐观:-)
    【解决方案2】:

    其实这是可以的。有一个名为:packed[1] 的库。但似乎该项目已被放弃,最后一次提交是 5 年前。引用它的自述文件:

    @packed
    def tag(self):
        share = get_share_link()
        return <a href={share}>Share on internet</a>
    
    # to:
    
    @packed
    def tag(self):
       share = get_share_link()
       return Elem(
            'a',
            {
                'href': share,
            },
            'Share on internet',
        )
    
    1. https://github.com/michaeljones/packed

    【讨论】:

    • 我真的希望有一个专门用于“X 有库吗?”的堆栈交换。输入问题,因为它们总是在这里被关闭真的很烦人;这是我想问这些问题的第一个地方,因为 SO 到处都是知道要推荐哪些库的人。
    • 我最近在寻找类似的东西,想知道为什么这种方法没有变得更流行,并且发现了另外两个具有相似想法的库:-github.com/gvanrossum/pyxl3-Pyxl 是一个开源包它扩展了 Python 以支持内联 HTML。 (还有一个 fork,github.com/pyxl4/pyxl4,但两者似乎或多或少都被放弃了。) - github.com/twidi/mixt - 直接在 python 中编写 html 组件,你就有了一个漂亮但有争议的 MIXture。 [...] 基于 pyxl。 (这个看起来更新,也更活跃。)
    猜你喜欢
    • 2015-02-14
    • 2017-06-03
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 2013-02-21
    • 2016-10-07
    相关资源
    最近更新 更多