Python、PyTables 和 Java - 综合整合

26 投票
4 回答
3384 浏览
提问于 2025-04-15 17:19

问题概述

如何让Python和Java更好地协同工作?

详细说明

我遇到了一些复杂的情况。尽量用图和文字来解释一下。下面是当前的系统架构:

当前系统架构

我们有一个用Java写的基于代理的建模仿真。它可以选择把数据写到本地的CSV文件,或者通过连接到Java服务器写到一个HDF5文件。每次仿真运行会产生超过一GB的数据,我们会运行几十次仿真。我们需要能够对同一场景的多次运行(使用不同的随机种子)进行汇总,以便观察一些趋势(比如最小值、最大值、中位数、平均值)。可以想象,移动这些CSV文件真是个噩梦;每次运行会产生多个文件,而且有些文件非常大。这就是我们想要转向HDF5解决方案的原因,所有研究的数据都存储在一个地方,而不是分散在几十个文本文件中。此外,由于HDF5是二进制文件格式,相比未压缩的CSV文件,它应该能节省不少空间。

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

问题

正如我之前提到的,CSV文件实在是太麻烦了,随着我们生成的数据越来越多,它们的管理变得越来越困难。此外,后处理代码做的事情超出了它的职责,实际上是在做一个非常简陋的关系数据库的工作(根据外键(唯一代理ID)在“表”(CSV文件)之间进行连接)。在这个系统中,以其他方式可视化数据也很困难(比如使用Prefuse、Processing、JMonkeyEngine获取一些原始数据的子集,以便在MatLab或SPSS中使用)。

解决方案?

我的团队决定,我们确实需要一种方法来过滤和查询现有数据,并进行跨表连接。考虑到这是一个“写一次,读多次”的情况,我们其实不需要真正的关系数据库的复杂性;我们只需要一种更好地处理HDF5文件的方式。我找到了一些相关的论文,比如一篇描述如何使用[XQuery作为HDF5文件的查询语言][3]的论文,但那篇论文提到需要编写一个编译器,将XQuery/XPath转换为原生的HDF5调用,这超出了我们的需求。 这时,[PyTables][4]出现了。它似乎正好满足我们的需求(提供两种不同的查询数据的方法,要么通过Python的列表推导,要么通过[内核级(C级)搜索][5])。

我设想的架构是这样的:

设想的架构

我不太确定的是,如何将用于查询的Python代码与提供HDF5文件的Java代码和处理数据的Java代码连接起来。显然,我希望重写大部分后处理代码,让优秀的PyTables来更优雅地完成这些查询。

Java/Python选项

简单的谷歌搜索给出了几种[Java和Python之间通信][7]的选项,但我对这个话题还很陌生,所以希望能得到一些实际的专业意见和对我设想架构的批评。看起来Python进程应该在与Datahose相同的机器上运行,这样就不需要通过网络传输大型的.h5文件,而是传输更小的、经过过滤的视图。[Pyro][8]似乎是一个有趣的选择——有没有人有这方面的经验?

4 个回答

0

你可以试试 Jython,这是一个可以在Java虚拟机上运行的Python解释器,它可以 import Java类。

Jython项目主页

不幸的是,我对这个话题了解的就这些了。

5

别把事情搞得太复杂。

你的Java程序可以很简单地启动一个单独的子进程来运行你的PyTables查询。让操作系统去做它最擅长的事情。

你的Java应用可以简单地创建一个进程,并把需要的参数作为命令行选项传递过去。这样,Java就可以继续做其他事情,而Python则在后台运行。

这样做在并发性能上有很大的优势。你的Python“后台”可以和Java的模拟“前台”同时运行。

13

这是个很棒的问题,涉及的方面很多。因为你没有提到具体的性能或架构限制,我会尽量给出一些全面的建议。

最初计划使用PyTables作为你其他元素和数据文件之间的中介层,这个想法挺不错的。不过,有一个设计限制没有提到,那就是数据处理中的一个关键点:哪些数据处理任务可以批量处理,哪些任务更适合实时处理。

这两者的区别在于“我们完全知道输入和输出,可以直接进行处理”(批量处理)和“我们知道输入,且需要为其他请求提供可用的数据”(实时处理)。这个区别对架构设计非常重要。看你的图,有几个关系暗示了不同的处理方式。

另外,在你的图中,不同类型的组件都使用了相同的符号,这让分析预期的性能和效率变得有点困难。

另一个重要的限制是你的IT基础设施。你是否有高速网络存储?如果有,中间文件就成了在基础设施各个部分之间共享数据的简单快速的方法,适合所有批量处理需求。你提到在运行Java模拟的同一台服务器上运行使用PyTables的应用程序,但这意味着这台服务器在读写数据时会有负载。(也就是说,模拟环境可能会受到无关软件查询数据时的影响。)

直接回答你的问题:

  • PyTables看起来是个不错的选择。
  • Python和Java之间有很多通信方式,但建议考虑一种与语言无关的通信方法,这样这些组件在必要时可以更换。找到支持Java和Python的库并尝试使用就可以了。你选择的API应该是相同的。(XML-RPC适合原型开发,因为它在标准库中,Google的Protocol Buffers或Facebook的Thrift是不错的生产选择。但如果数据是可预测和可批处理的,简单地“写入中间文件”也是非常有效的。)

为了更好地帮助设计过程,明确你的需求:

很容易只看问题的一小部分,做一些合理的假设,然后直接进入解决方案评估。但更好的方法是全面看待问题,清楚了解你的限制。我建议你这样做:

  • 创建两个关于你当前架构的图,物理图和逻辑图。
    • 在物理图上,为每台物理服务器创建框,并绘制它们之间的物理连接。
      • 确保标注每台服务器可用的资源,以及每个连接的类型和资源。
      • 如果有可能有用的物理硬件,即使在当前设置中没有使用,也要包括在内。(如果你有SAN可用,但没有使用,最好也把它写上,以防解决方案需要。)
    • 在逻辑图上,为你当前架构中运行的每个应用程序创建框。
      • 将相关库作为框放在应用程序框内。(这很重要,因为你未来的解决方案图中有PyTables作为一个框,但它只是一个库,不能单独工作。)
      • 将磁盘资源(如HDF5和CSV文件)画成圆柱体。
      • 根据需要用箭头连接应用程序与其他应用程序和资源。箭头总是从“执行者”指向“目标”。例如,如果一个应用程序写入HDF5文件,箭头就从应用程序指向文件;如果一个应用程序读取CSV文件,箭头就从应用程序指向文件。
      • 每个箭头都必须标注通信机制。没有标注的箭头只显示关系,但不显示什么关系,因此无法帮助你做决策或沟通限制。

完成这些图后,做几份副本,然后在上面开始做数据流的草图。为每个需要你原始数据的“终端”应用程序准备一份图,从模拟开始,到终端结束,画出一个流畅的箭头。每当你的数据箭头跨越通信/协议箭头时,记下数据的变化(如果有的话)。

此时,如果你和你的团队都同意纸上的内容,那么你就以一种容易沟通的方式解释了你当前的架构。(不仅仅是这里的帮助者,还有老板、项目经理和其他决策者。)

开始规划你的解决方案时,查看你的数据流图,从终端向起点反向工作,创建一个嵌套列表,包含每个应用程序和中间格式,直到回到起点。然后,列出每个应用程序的需求。确保包括:

  • 这个应用程序可以使用什么数据格式或方法进行通信。
  • 它实际需要什么数据。(这个数据是始终相同,还是会根据其他需求变化?)
  • 它需要多频繁。
  • 大约需要多少资源。
  • 这个应用程序现在做得不好的事情。
  • 这个应用程序现在能做但没有做的事情。

如果你能做好这个列表,你就能清楚地定义你选择的协议和解决方案。你可以查看数据跨越通信线的情况,并比较双方的需求列表。

你已经描述了一个特定情况,你有很多Java后处理代码在对CSV文件中的数据表进行“连接”,这就是“现在可以做但做得不好的”情况。所以你要查看通信的另一方,看看另一方是否能更好地完成这个任务。此时,另一方是CSV文件,而之前是模拟,所以在当前架构中,没有其他东西能做得更好。

因此,你提出了一个新的Python应用程序,使用PyTables库来改善这个过程。听起来不错!但在你的下一个图中,你添加了许多与“PyTables”通信的其他东西。现在我们超出了StackOverflow小组的理解,因为我们不知道那些其他应用程序的需求。但如果你按照上面提到的方式列出需求,你就会知道该考虑什么。也许你的Python应用程序使用PyTables来对HDF5文件进行查询,可以支持所有这些应用程序。也许它只支持一两个。也许它会为后处理程序提供实时查询,但定期为其他应用程序写入中间文件。我们无法确定,但通过规划,你可以做到。

一些最终的指导原则:

  • 保持简单!复杂性是敌人。你的解决方案越复杂,实施起来就越困难,失败的可能性也越大。使用最少的操作,使用最简单的操作。有时,处理所有其他部分查询的一个应用程序是最简单的。有时,一个处理“实时”查询的应用程序和一个处理“批量请求”的应用程序分开会更好。
  • 保持简单!这很重要!不要编写任何可以由现成的东西完成的代码。(这就是中间文件如此优秀的原因,操作系统处理所有复杂的部分。)此外,你提到关系数据库开销太大,但要考虑关系数据库还带有非常丰富且知名的查询语言、相应的网络通信协议,并且你不需要开发任何东西来使用它!你提出的任何解决方案都必须比现成的解决方案更好,后者肯定会很好地工作,否则就不是最佳解决方案。
  • 经常参考你的物理层文档,以便了解你考虑的资源使用情况。慢速网络连接或将过多负载放在一台服务器上都可能排除其他好的解决方案。
  • 保存这些文档。无论你决定什么,过程中生成的文档都是有价值的。将它们做成Wiki或存档,以便在相关话题出现时再次使用。

至于直接问题“如何让Python和Java和谐共处?”的答案就是“使用一种与语言无关的通信方法。”实际上,Python和Java在你描述的问题集中并不重要。重要的是流动的数据。任何能够轻松有效地共享数据的方式都很好。

撰写回答