Python,PyTables,Java-将所有内容联系在一起

26

问题概述

如何使Python和Java相互配合以实现最佳效果?

详细解释

我面临一个比较复杂的情况,我会尽力通过图片和文字来解释。当前系统架构如下:

Current system architecture

我们有一个基于代理模型的Java编写的模拟程序,可以选择将结果写入本地CSV文件或连接到Java服务器并写入HDF5文件。每次运行模拟产生超过一千兆字节的数据,并且我们需要运行数十次模拟才能对同一场景下的多个运行进行聚合(使用不同的随机种子)以查看某些趋势(例如最小值、最大值、中位数和平均值)。正如您所想象的那样,试图移动所有这些CSV文件是非常困难的;每次运行会生成多个文件,其中一些文件非常大。这就是为什么我们试图采用HDF5解决方案的原因,在此方案中,所有研究的数据都存储在一个地方,而不是分散在几十个纯文本文件中。此外,由于它是一种二进制文件格式,与未压缩的CSV相比,应该能够获得明显的空间节约。

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

问题

正如我之前提到的,CSV格式已经不可行了,随着我们从模拟中生成越来越多的数据,CSV文件无法很好地扩展。此外,后处理代码要做的事情超出了它本应该做的,基本上执行了一个非常非常简陋的关系型数据库的工作(根据外键(唯一代理商ID)在“表格”(CSV文件)之间进行连接)。在这个系统中,以其他方式查看数据也很困难(例如,使用Prefuse、Processing、JMonkeyEngine在MatLab或SPSS中获取某些原始数据的子集)。

解决方案?

我们的小组决定需要一种过滤和查询我们拥有的数据的方法,以及执行交叉表联接。鉴于这是一种只写入一次但需要多次读取的情况,我们真的不需要真正关系型数据库的开销;相反,我们只需要一种在HDF5文件上放置更好的前端的方法。我发现了一些论文,比如描述如何在HDF5文件上使用[XQuery作为查询语言][3],但论文描述了必须编写编译器将XQuery/XPath转换为本机HDF5调用,远远超出了我们的需求。 进入[PyTables][4]。它似乎正好符合我们的要求(提供两种不同的查询数据的方式,通过Python列表推导或通过[内核(C级别)搜索][5])。

我设想的架构如下: Envisioned architecture

我真正不确定的是如何将编写用于查询的python代码与提供HDF5文件的Java代码以及后处理数据的Java代码链接在一起。显然,我将重写许多隐含进行查询并代替让优秀的PyTables更加优雅地完成此任务的后处理代码。

Java/Python选项

一次简单的谷歌搜索就可以找到几种[Java和Python之间通信][7]的选项,但是我对这个主题非常陌生,所以我正在寻找一些实际的专业知识和对所提出架构的批评。看起来Python进程应该在与Datahose相同的机器上运行,这样大的.h5文件就不必通过网络传输,而是仅传输其较小、经过过滤的视图给客户端。[Pyro][8]似乎是一个有趣的选择——有人有使用它的经验吗?

2
我对Python了解不够,无法回答,但我想说这是一个写得非常好且图文并茂的问题。我能提供的建议是,如果您使用Jython,您可以从Python中调用Java代码和库,我相信也可以从Java中调用Jython代码。此外,虽然HDF5是一个为大型数据集设计的精美格式,但如果您的数据真正关系到复杂的分析,使用数据库仍然更加合理,因为它可以轻松进行SQL查询。 - BobMcGee
1
+1 很棒的问题,表达得非常清晰明了 - Simon
1
这或许是一个天真的问题,但为什么你需要让Java与Python交互呢?你似乎有一个很好的分层架构,其中提供了通过HDF5文件表达的数据接口。从你的问题中不清楚你想在Java中使用Python做什么 - 或者反过来 - 以及为什么这样做。 - Simon
关系型数据库不一定需要高开销。你看过像SQLite这样的东西吗? - Ichorus
回复:Ichorus:如果 HDF5 数据仓库计划失败,我建议使用像 SQLite 这样的 RDBMS,但我们从未实施过它以查看其性能。当我们不需要任何行级锁定或事务特性时,它似乎是过度的。 - I82Much
显示剩余2条评论
4个回答

13
这是一个重要的问题,需要考虑很多因素。既然您没有提到任何具体的性能或架构限制,我会尝试提供最全面的建议。
使用PyTables作为其他元素和数据文件之间中介层的初始计划似乎很稳健。但是,未提及的一个设计限制是所有数据处理中最关键的限制之一:哪些数据处理任务可以批量处理,哪些数据处理任务更像是实时流处理。
批量处理和实时流处理之间的这种区分对于架构问题来说至关重要。查看您的图表,有几个关系暗示不同的处理方式。
此外,在您的图表上,有不同类型的组件都使用相同的符号。这使得分析预期的性能和效率有点困难。
另一个重要的约束是您的IT基础设施。您是否拥有高速网络可用存储?如果是,中间文件成为在批量处理需求中分享基础架构各个元素数据的绝佳、简单且快速的方法。您提到在运行Java模拟的服务器上运行使用PyTables的应用程序。但是,这意味着服务器将承受写入和读取数据的负载。(也就是说,当无关软件查询数据时,模拟环境可能会受到影响。)
直接回答您的问题:
- PyTables看起来很匹配。 - Python和Java之间有许多通信方式,但请考虑采用无语言限制的通信方法,以便这些组件在必要时可以更改。这只是找到支持Java和Python的库并尝试它们一样简单。不管您选择使用任何库实现的API应该是相同的。(XML-RPC对于原型设计也是可以的,因为它在标准库中,Google的Protocol Buffers或Facebook的Thrift则是生产环境的好选择。但是,如果数据可预测且可批处理,请不要低估“将事物写入中间文件”的简单性。)
为了更好地帮助设计过程并明确您的需求:
很容易看待问题的一小部分,做出一些合理的假设,并进入解决方案评估阶段。但是,更好的方法是全面看待问题,并清楚地了解您的约束条件。我可以建议以下流程:
  • 创建当前架构的物理和逻辑两个图表。
    • 在物理图表上,为每个物理服务器创建一个方框,并绘制它们之间的物理连接。
      • 请确保为每个服务器标记可用资源以及每个连接类型和可用资源。
      • 如果有一些实际硬件并未用于当前设置但可能会有用,请将其包含在内。(如果您有一个可用的SAN,但没有使用它,请将其包括在内,以防将来可能需要。)
    • 在逻辑图表上,为当前架构中运行的每个应用程序创建方框。
      • 将相关库作为方框内部的组成部分包含在应用程序方框中。(这很重要,因为您的未来解决方案图表当前将PyTables作为一个方框,但它只是一个库,无法自主执行任何操作。)
      • 将磁盘资源(如HDF5和CSV文件)绘制为圆柱体。
      • 根据需要,将应用程序与其他应用程序和资源连接起来。始终从“操作者”到“目标”绘制箭头。因此,如果应用程序写入HDF5文件,则箭头从应用程序指向文件。如果应用程序读取CSV文件,则箭头从应用程序指向文件。
      • 每个箭头都必须标记通信机制。未标记的箭头显示一种关系,但它们并不显示何种关系,因此它们无法帮助您做出决策或传达约束。

完成这些图表后,请制作几份副本,然后在上面进行数据流草图。针对需要原始数据的每个“终点”应用程序的每个图表副本,从模拟开始,以几乎连续的箭头流结束到终点。如果您的数据箭头横跨通信/协议箭头,请记录数据如何更改(如果有)。

此时,如果您和团队对纸张上的内容达成共识,则已经以一种易于传达给任何人的方式解释了当前架构。(不仅是在stackoverflow上的助手,还包括老板、项目经理和其他财务持有者。)

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

  • 这个应用程序可以使用什么数据格式或方法进行通信。
  • 它实际上需要什么数据。(始终相同还是根据其他要求随意更改?)
  • 它需要多久才能得到它。
  • 该应用程序大约需要多少资源。
  • 该应用程序现在做的事情不太好。
  • 这个应用程序现在能做什么是有帮助的,但它没有做。

如果您对此列表做得很好,您就可以了解如何定义所选择的协议和解决方案。 您查看数据穿过通信线路的情况,并比较通信两侧的要求列表。

您已经描述了一个特定的情况,在这种情况下,您有许多正在执行CSV文件中数据表“连接”的Java后处理代码,这是一个“现在需要但不太好”的功能。 因此,您查看该通信的另一侧,以查看另一侧是否可以很好地执行该操作。 目前,另一侧是CSV文件,而在此之前是模拟,因此没有任何东西可以在当前架构中更好地执行该操作。

因此,您提出了一个新的Python应用程序,它使用PyTables库来使该过程更好。 到目前为止,听起来不错! 但是在下一个图表中,您添加了许多其他与“PyTables”交谈的内容。 现在我们已经超出了StackOverflow团队的理解范围,因为我们不知道这些其他应用程序的要求。 但是如果您像上面提到的那样制作要求列表,您将确切地知道要考虑什么。 也许您的使用PyTables在HDF5文件上提供查询的Python应用程序可以支持所有这些应用程序。 也许它只支持其中一两个。 也许它为后处理器提供实时查询,但会定期为其他应用程序编写中间文件。 我们无法确定,但是通过规划,您可以。

一些最终准则:

  • 保持简单! 复杂性是敌人。解决方案越复杂,实施起来就越困难,也越有可能失败。使用尽可能少的操作,使用尽可能简单的操作。有时,只需一个应用程序即可处理整个架构中所有其他部分的查询,这是最简单的方法。有时,一个应用程序用于处理“实时”查询,另一个应用程序用于处理“批量请求”更好。
  • 保持简单! 这很重要!不要编写已经可以为您完成的任何内容。(这就是为什么中间文件非常好,操作系统处理所有困难的部分的原因。)此外,您提到关系型数据库的开销太大,但请考虑,关系型数据库还带有非常具有表现力且广为人知的查询语言,以及与之相对应的网络通信协议,并且您不必开发任何东西来使用它!无论您想出什么解决方案,都必须比使用现成解决方案更好,后者肯定会非常好,否则它就不是最佳解决方案。
  • 经常参考物理层文档,以便了解您的考虑所需的资源使用情况。慢速网络链接或将太多内容放在一个服务器上都可能排除本来不错的解决方案。
  • 保存这些文档。 无论您做出什么决定,您在过程中生成的文档都是有价值的。使用Wiki进行归档或存储它们,以便在下次需要时轻松查阅。

对于直接问题“如何让Python和Java相互协作?”,答案非常简单:“使用语言不可知的通信方法。” 事实上,Python和Java对于您所描述的问题集都不重要。重要的是流经其中的数据。任何能够轻松有效地共享数据的方法都可以正常运行。


同意。如果不知道需要PyTables层做什么,很难知道提问者需要什么。一些使用案例会很有帮助。 - AFoglia
这是我见过的最完整、全面的回答,给你点赞。当然,你是对的,我应该想办法将系统解耦,并编写一个程序不可知的接口,以便以后更容易地进行修改。对于那个奇怪的图表,我很抱歉;我还是新手,之前没有制作过太多的图表/图形来说明复杂系统的组件。我一定会采纳你的建议,修改架构图,并在这里发布我的结果,让其他人也受益。 - I82Much

5
不要让这件事变得比必要的还要复杂。
您的Java进程可以简单地生成一个单独的子进程来运行PyTables查询。让操作系统发挥其最佳功能。
您的Java应用程序可以简单地分叉一个进程,该进程具有必要的参数作为命令行选项。然后,您的Java可以继续下一步,而Python在后台运行。
这在并发性能方面具有巨大优势。您的Python“后端”与Java仿真“前端”并发运行。

0
你可以尝试使用Jython,它是一个针对JVM的Python解释器,可以import Java类。

Jython项目主页

不幸的是,这就是我所知道的全部内容。


PyTables 需要 NumPy,而据我所知,NumPy 不能与 Jython 兼容。虽然他可能可以从 Jython 访问其 Java HDF5 库。 - AFoglia

0

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

只是想知道你的情况怎么样了?我们在工作中有一个非常非常相似的情况-只是模拟是用C编写的,存储格式是二进制文件。每当老板需要不同的摘要时,我们就必须制作/修改手写代码来执行摘要。我们的二进制文件大小约为10 GB,每年模拟都有一个这样的文件,因此可以想象,当我们想以不同的种子等运行它时,事情变得棘手。

我刚刚发现了pyTables,并有了类似于你的想法。我希望将我们的存储格式更改为hdf5,然后使用pytables运行我们的汇总报告/查询。其中一部分涉及从每年的表中连接表。你在使用pytables进行这些类型的“连接”方面有很大的成功吗?


1
实际上,在有机会实现本文中的任何想法之前,我已经转向了另一个项目。这就是生活。我不认为团队中的其他人继续使用PyTables的想法。我仍然认为它是值得的。 - I82Much

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接