在 python 中集成 OCaml - 如何从 python 开始一个 ocaml 会话?

Integrating OCaml in python - How to hold an ocaml session from python?

我想要 python GUI 在后台有一个 OCaml 进程。我想在程序的整个生命周期中保持一个会话,并根据用户输入调用一些 OCaml 命令并检索 OCaml 的输出。一些 OCaml 变量和结构可能会在此过程中定义,所以我想保持一个正在进行的会话。

我的解决方案是使用 popen 保持 OCaml 顶层进程并与其 stdin 和 stdout 交互。由于以下几个原因,这纯粹对我有用: 1. 我不知道 OCaml 计算何时完成,也不知道它的输出是否完整或还有更多输出(特别是如果评估需要一些时间,并且如果调用了多个 OCaml 命令)。 2. 我没有固有的方法来判断 OCaml 命令 运行 是否顺利,或者可能有 OCaml 警告或错误。 3. 我丢失了 OCaml 输出的结构。例如,如果输出分布在多行上,我无法分辨哪些行由于行大小而被断开,哪些行原本是单独的行。

我知道有一些关于 python 与 OCaml 结合的讨论和一些软件包,但它们都是来自 OCaml 的 运行 python 命令,而我需要相反的东西。

如果您想 运行 OCaml 在一个单独的进程中,您需要将 OCaml 调用包装在一个函数中,该函数收集所有结果并 returns 它们以有用的序列化格式,例如JSON。或者,您可以尝试编写一个使用 OCaml toplevel as a library 的 Python C 扩展,但这可能需要相当多的工作。

如果您需要 Python 和 OCaml 代码之间的强大通信,确实应该有两个独立的 "master" 进程(将它们视为网络节点)。

正如@Sven Marnach 已经提到的,实现这个的一个很好的选择是通过基于 JSON 的协议 link 这两个进程。

更方便的方法是使用 Google 的 gRPC 框架 (https://grpc.io/) and communicate via Protobuf messages (https://developers.google.com/protocol-buffers/)。该框架非常好用。不幸的是,目前还没有对 OCaml 的支持,但我认为您可以将 OCaml main 薄包装到薄 Python 层中,或者将其转换为 JS。然后,您需要做的就是将您的函数连接到 gRPC 接口。

系统的外观如下:

+----------+   +------+   +---Thin Python wrapper / JS wrapper---+
|   Your   |   |      |   |  +--------------------------------+  |
|  Python  |<->| gRPC |<->|  |        Your OCaml app          |  |
|   app    |   |      |   |  +--------------------------------+  |
+----------+   +------+   +--------------------------------------+

P.S. 我在与您的问题类似的问题中使用相同的方法(但 GUI 在 Java 中)。我会说它非常方便,开发速度快,并且易于扩展。

P.P.S. 你并不孤单:)。这是一位(前任?)Google 员工 (https://arxiv.org/abs/1702.01715) 的一篇论文的有趣摘录:

Software engineers at Google are strongly encouraged to program in one of five officially-approved programming languages at Google: C++, Java, Python, Go, or JavaScript​.

Interoperation between these different programming languages is done mainly using Protocol Buffers​. Protocol Buffers is a way of encoding structured data in an efficient yet extensible way. It includes a domain-specific language for specifying structured data, together with a compiler that takes in such descriptions and generates code in C++, Java, Python, for constructing, accessing, serializing, and deserializing these objects. Google’s version of Protocol Buffers is integrated with Google’s RPC libraries, enabling simple cross-language RPCs, with serialization and deserialization of requests and responses handled automatically by the RPC framework.

作为补充说明,完全有可能 运行 一个单独的顶层进程并向其发送输入短语并读取相应的输出。检测顶层输出结束的技巧是在每个输入短语后添加一个保护短语:而不是只发送 f ();; 到顶层进程,可以发送 f ();; "end_of_input";; 然后观察顶层输出对应于 "end_of_input";;(又名 - : string = "end_of_input")。我的经验是,错误和警告通常很容易从顶层输出中检测或解析;所以唯一缺少的一点是代码的格式。