如何在python脚本中嵌入JSX这样的语言?

2024-05-17 11:58:18 发布

您现在位置:Python中文网/ 问答频道 /正文

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

理想情况下,应该可以将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代码。它会转化为类似的东西:

^{pr2}$

问题是:我该如何编写这样一个transpiler?在

此外,我们还考虑了不直接将JSX嵌入python代码中,而是返回一个包含独立解析的JSX的字符串。这是一个更好/更容易的方法吗?在


Tags: 代码importdiv模板gettitlecontextpage
2条回答

实际上,这是可能的。有一个库叫做:packaged[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

我认为这基本上是一个过于宽泛的问题,任何答案都将滑向SO关于意见的指导方针的边缘。你本质上是在为一个复杂的问题征求设计建议,所以并不是真正的目的。在

不过,这是个有趣的问题。我将尝试解决这些问题,而不必过于深入地探讨固执己见的设计(因为我对这个问题确实有意见)。在

  1. 运输是实用的,至少在理论上是这样,如果你能做到,它会给你合理的性能。

  2. 重复地重新分析模板字符串给我的印象是低效和复杂的;复杂性与计算嵌入的Python代码有关,您将希望在定义字符串文本的范围内执行此操作,这可能不是解析它的范围。

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

  4. 在另一种语言中嵌入伪HTML的主要问题是检测<何时是比较运算符以及何时启动模板。最简单的解决方案是仅当<作为一个完整的标记进行词汇分析时(这样<=始终是一个运算符),后面跟着一个标识符,并且在需要表达式的语法环境中遇到时,才允许使用模板。

  5. 上面的最后一个要求是确保3 < count(例如)不会欺骗transpiler认为它将看到一个<count...>组件。我确信在Python中可以使用基于前面标记的简单词法规则,但是需要进行完整的语法分析来验证

  6. 一旦启动了一个模板,它将一直持续到您到达匹配的结束标记;如果需要匹配标记,这非常简单。但它更适合自顶向下的解析,而不是自下而上的解析,因为结束标记匹配是上下文敏感的。如果你在词法分析和句法分析之间有密切的合作,这很容易做到,但这种合作有时是不受欢迎的:-)

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

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

  9. transpiler的另一个挑战是将其与Python的模块系统集成。Pythonic集成可能建议在导入模块时执行移植。另一个h而且,您可能希望能够分发一个预传输捆绑包,它可以在不安装transpiler的情况下使用,也不依赖于transpiler的特定版本。如果你花点时间仔细考虑一下,也许可以避免以后的问题。(例如,Ply问题导致无法将Ply项目捆绑到单个文件分发系统中。)

希望这有点帮助。在

相关问题 更多 >