25

简而言之问题

让 Python 和 Java 相互配合的最佳方式是什么?

更详细的解释

我的情况有点复杂。我会尽量用图片和文字来解释。这是当前的系统架构:

当前系统架构

我们有一个用 Java 编写的基于代理的建模模拟。它可以选择在本地写入 CSV 文件,也可以通过与 Java 服务器的连接远程写入HDF5文件。每次模拟运行都会产生超过 1 GB 的数据,我们会运行数十次模拟。我们需要能够对同一场景的多次运行(使用不同的随机种子)进行聚合,以便查看一些趋势(例如,最小值、最大值、中值、平均值)。可以想象,试图移动所有这些 CSV 文件是一场噩梦。每次运行会产生多个文件,就像我说的那样,其中一些是巨大的。这就是我们一直试图转向 HDF5 解决方案的原因,在该解决方案中,一项研究的所有数据都存储在一个地方,而不是分散在几十个纯文本文件中。此外,由于它是二进制文件格式,与未压缩的 CSVS 相比,它应该能够节省大量空间。

如图所示,我们对模拟的原始输出数据进行的当前后处理也是在 Java 中进行的,并读取本地输出生成的 CSV 文件。这个后处理模块使用 JFreeChart 创建一些与仿真相关的图表和图形。

问题

正如我之前提到的,CSV 确实站不住脚,并且随着我们从模拟中生成越来越多的数据,它的扩展性也不好。此外,后处理代码做的比它应该做的更多,本质上是在执行一个非常非常穷人的关系数据库的工作(基于外键(唯一代理 ID)跨“表”(csv 文件)进行连接). 在这个系统中以其他方式可视化数据也很困难(例如 Prefuse、Processing、JMonkeyEngine 在 MatLab 或 SPSS 中获取原始数据的一些子集)。

解决方案?

我的团队认为我们确实需要一种过滤和查询我们拥有的数据以及执行跨表连接的方法。鉴于这是一次写入、多次读取的情况,我们真的不需要真正的关系数据库的开销;相反,我们只需要一些方法在 HDF5 文件上放置一个更好的前端。我找到了几篇关于此的论文,例如一篇描述如何使用XQuery 作为 HDF5 文件的查询语言的论文,但该论文描述了必须编写一个编译器来将 XQuery/XPath 转换为原生 HDF5 调用,这远远超出了我们的需要。输入PyTables。它似乎完全符合我们的需要(提供两种不同的数据查询方式,通过 Python 列表理解或通过内核(C 级)搜索

我设想的建议架构是这样的: 设想的架构

我不太确定如何将用于查询的 Python 代码、提供 HDF5 文件的 Java 代码以及对数据进行后处理的 Java 代码链接在一起。显然,我想重写大部分隐式执行查询的后处理代码,而是让优秀的 PyTables 更优雅地完成这件事。

Java/Python 选项

一个简单的谷歌搜索出现了一些用于在 Java 和 Python 之间进行通信的选项,但我对这个主题太陌生了,所以我正在寻找一些实际的专业知识和对提议的架构的批评。看起来 Python 进程应该与 Datahose 在同一台机器上运行,这样大的 .h5 文件就不必通过网络传输,而是将更小的过滤视图传输给客户端。 Pyro似乎是一个有趣的选择——有人有这方面的经验吗?

4

4 回答 4

13

这是一个史诗般的问题,有很多考虑因素。由于您没有提及任何特定的性能或架构限制,我将尝试提供最全面的建议。

使用 PyTables 作为其他元素和数据文件之间的中间层的最初计划似乎很可靠。但是,没有提到的一个设计约束是所有数据处理中最关键的约束之一:这些数据处理任务中的哪些可以以批处理方式完成,哪些数据处理任务更像是实时流。

“我们确切地知道我们的输入和输出,并且可以进行处理”(批处理)和“我们知道我们的输入以及需要什么才能被其他东西询问”(实时)之间的这种区别对架构问题产生了很大的影响. 查看您的图表,有几种关系暗示了不同的处理方式。

此外,在您的图表上,您有不同类型的组件都使用相同的符号。这使得分析预期的性能和效率有点困难。

另一个重要的制约因素是您的 IT 基础架构。您是否有高速网络可用存储?如果您这样做,中间文件将成为一种出色、简单且快速的方式,可以在您的基础架构元素之间共享数据,以满足所有批处理需求。您提到在运行 Java 模拟的同一台服务器上运行 PyTables-using-application。但是,这意味着服务器将承受写入和读取数据的负载。(也就是说,仿真环境在查询数据时可能会受到无关软件需求的影响。)

直接回答您的问题:

  • PyTables 看起来很不错。
  • Python 和 Java 有多种通信方式,但请考虑一种与语言无关的通信方法,以便以后如有必要可以更改这些组件。这就像找到支持 Java 和 Python 的库并尝试它们一样简单。无论如何,您选择使用任何库实现的 API 都应该是相同的。(XML-RPC 可以很好地用于原型设计,因为它在标准库中,Google 的 Protocol Buffers 或 Facebook 的 Thrift 是很好的生产选择。但是不要低估如果数据是“将东西写入中间文件”是多么伟大和简单可预测和可批处理。

为了更多地帮助设计过程并充实您的需求:

看一小块拼图,做出一些合理的假设,然后跳入解决方案评估是很容易的。但是,在清楚地了解您的约束条件的情况下,从整体上看待问题会更好。我可以建议这个过程:

  • 创建当前架构的两个图表,物理的和逻辑的。
    • 在物理图上,为每个物理服务器创建框,并绘制每个之间的物理连接图。
      • 一定要标记每个服务器可用的资源以及每个连接可用的类型和资源。
      • 如果可能有用,请包括当前设置中未涉及的物理硬件。(如果您有可用的 SAN,但没有使用它,请将它包含在解决方案可能需要的情况下。)
    • 在逻辑图上,为当前架构中运行的 每个应用程序创建框。
      • 将相关库作为应用程序框内的框包含在内。(这很重要,因为您未来的解决方案图目前将 PyTables 作为一个盒子,但它只是一个库,不能靠它自己做任何事情。)
      • 将磁盘资源(如 HDF5 和 CSV 文件)绘制为柱面。
      • 根据需要将带有箭头的应用程序连接到其他应用程序和资源。始终绘制“演员”“目标”的箭头。因此,如果应用程序写入 HDF5 文件,它们的箭头会从应用程序指向文件。如果应用程序读取 CSV 文件,箭头会从应用程序指向文件。
      • 每个箭头都必须标有通信机制。未标记的箭头显示了一种关系,但它们不显示什么关系,因此它们不会帮助您做出决定或传达约束。

一旦你完成了这些图表,复制它们,然后在它们上面开始做数据流涂鸦。为每个需要原始数据的“终点”应用程序复制一份图表,从模拟开始,并在终点以一个非常实心的流动箭头结束。每当您的数据箭头流经通信/协议箭头时,请记下数据如何更改(如果有)。

此时,如果您和您的团队都同意纸上的内容,那么您已经以一种应该易于与任何人交流的方式解释了您当前的架构。(不仅是 stackoverflow 上的帮手,还有老板、项目经理和其他钱包持有者。)

要开始规划您的解决方案,请查看您的数据流图并从端点向后工作,并创建一个嵌套列表,其中包含每个应用程序和返回起点的中间格式。然后,列出每个应用程序的要求。一定要展示:

  • 此应用程序可以使用哪些数据格式或方法进行通信。
  • 它真正想要什么数据。(这总是一样的还是会根据其他要求随心所欲地改变?)
  • 它多久需要一次。
  • 应用程序大约需要多少资源。
  • 现在应用程序做得不好,它做了什么。
  • 这个应用程序现在可以做什么会有所帮助,但它没有做。

如果您在此列表中做得很好,您可以看到这将如何帮助定义您选择的协议和解决方案。您查看数据通过通信线路的情况,并比较通信双方的需求列表。

您已经描述了一种特殊情况,您有相当多的 Java 后处理代码正在对 CSV 文件中的数据表进行“连接”,这是“现在做,但做得不好”。所以你看看沟通的另一方,看看对方是否能做好这件事。在这一点上,另一边是 CSV 文件,在此之前是模拟,所以不,在当前架构中没有什么比这更好的了。

因此,您提出了一个新的 Python 应用程序,该应用程序使用 PyTables 库来改进该过程。到目前为止听起来不错!但是在您的下一个图表中,您添加了一堆与“PyTables”对话的其他内容。现在我们已经扩展了对 StackOverflow 小组的理解,因为我们不知道其他应用程序的需求。但是,如果您像上面提到的那样制作要求列表,您就会确切地知道要考虑什么。也许您使用 PyTables 提供对 HDF5 文件的查询的 Python 应用程序可以支持所有这些应用程序。也许它只会支持其中的一两个。也许它会为后处理器提供实时查询,但会定期为其他应用程序编写中间文件。我们不能说,但通过计划,你可以。

一些最终指南:

  • 保持简单!这里的敌人是复杂性。您的解决方案越复杂,实施该解决方案的难度就越大,失败的可能性就越大。使用最少数量的操作,使用最简单的操作。有时,只有一个应用程序来处理架构中所有其他部分的查询是最简单的。有时,处理“实时”查询的应用程序和处理“批量请求”的单独应用程序会更好。
  • 保持简单! 这是一件大事!不要写任何已经可以为你完成的东西。(这就是为什么中间文件可以这么大,操作系统处理所有困难的部分。)另外,你提到关系数据库的开销太大,但考虑到关系数据库还带有一个非常有表现力和众所周知的查询语言,与之配套的网络通信协议,无需开发任何东西即可使用它!无论你想出什么解决方案,都必须使用现成的解决方案更好,当然,非常好,否则它不是最好的解决方案。
  • 经常参考您的物理层文档,以便了解您考虑的资源使用情况。缓慢的网络链接或在一台服务器上放置太多都可以排除其他好的解决方案。
  • 保存这些文档。无论您做出什么决定,您在此过程中生成的文档都是有价值的。将它们 Wiki 或归档,这样当话题出现时,您可以再次将它们抽出来。

以及直接问题的答案,“如何让 Python 和 Java 一起玩得很好?” 只是“使用与语言无关的交流方法”。事情的真相是 Python 和 Java 对你描述的问题集都不重要。重要的是流经它的数据。任何可以轻松有效地共享数据的东西都会很好。

于 2009-12-23T17:27:12.660 回答
5

不要使这比它需要的更复杂。

您的 Java 进程可以——简单地——产生一个单独的子进程来运行你的 PyTables 查询。让操作系统做操作系统最擅长的事情。

您的 Java 应用程序可以简单地派生一个具有必要参数作为命令行选项的进程。然后,当 Python 在后台运行时,您的 Java 可以继续进行下一件事。

这在并发性能方面具有巨大的优势。您的 Python“后端”与您的 Java 模拟“前端”同时运行。

于 2009-12-23T16:32:28.847 回答
0

您可以尝试Jythonimport ,这是一个用于Java 类的 JVM 的 Python 解释器。

Jython 项目主页

不幸的是,这就是我所知道的关于这个主题的全部内容。

于 2009-12-23T16:19:31.997 回答
0

不确定这是否是好的礼仪。我无法将我的所有评论都放入正常评论中,并且该帖子已 8 个月没有活动。

只是想看看你的情况如何?我们在我工作的地方有一个非常非常相似的情况——只有模拟是用 C 语言编写的,存储格式是二进制文件。每次老板想要不同的总结时,我们都必须制作/修改手写代码来做总结。我们的二进制文件大小约为 10 GB,每年都有一个模拟文件,所以你可以想象,当我们想用不同的种子等运行它时,事情会变得很棘手。

我刚刚发现了 pyTables,并且和你的想法相似。我希望将我们的存储格式更改为 hdf5,然后使用 pytables 运行我们的摘要报告/查询。其中一部分涉及加入每年的表格。使用 pytables 进行这些类型的“连接”时,您是否很幸运?

于 2010-08-21T22:55:46.237 回答