从Ruby调用Python - PyPy兼容性

3
我想从Ruby中调用Python代码。已经有一些现有的工具可以做到这一点,而且在这个网站上也有一些关于此事的问题,推荐使用http://rubypython.rubyforge.org/,该工具通过在Ruby中嵌入Python解释器来实现。我正在开发一个应用程序,其中使用了Python特有的库(即graph-tool,我有使用它而不是RGL的原因),但最终项目是在Rails中完成的,因此让Ruby代码来控制工作将是理想的选择。我希望它能够快速运行,因此我使用PyPy。是否有一种方法可以将PyPy解释器嵌入到Ruby代码中,或者使rubypython中的Python解释器运行PyPy?

1
你考虑过使用在JVM上构建的Python虚拟机并使用JRuby吗?如果采取这种方法,在它们之间共享数据将变得非常简单。 - zetavolt
@ZephyrPellerin:这并没有真正帮助到OP的问题。如果他只想使用任何Python,他已经通过rubypython和标准的CPython解释器得到了它。他想要运行PyPy而不是Jython。能够运行Jython并不能让他更接近目标。 - abarnert
说“我希望它速度更快,所以我使用PyPy”有点误导人。针对Python的某些代码块,PyPy的运行速度可以快0.1倍到20倍不等。如果你实际上已经分析了某些瓶颈代码,并且PyPy对该瓶颈代码提供了可衡量的性能增益,则这是一个合理的问题。在这一点上,你必须决定是否更容易重新编写代码以在PyPy和ruby之间进行更间接的通信(例如通过popen或通过套接字),还是找到一种不同的方法来优化该瓶颈(例如使用Cython)。 - abarnert
我们可以稍微挑战您的想法吗?为什么不使用Django而不是Rails呢?或者为什么不同时使用Rails和不同的图形库,比如Neo4J,或者如果您使用JRuby平台,还有许多可用的Java库? - Mark Thomas
Rails被其他人设置在项目中,这个图形库有一些算法是我在其他地方找不到的(比如子图同构和模体识别),所以真正需要保留这两个算法。 - jclancy
显示剩余2条评论
1个回答

5
不行,除非付出大量的工作。
首先,RubyPython并没有真正包含一个嵌入式的Python解释器;它只是在运行时包装了解释器。如文档所示,你可以使用任何你想要的Python来运行它,例如:
>> RubyPython.start(:python_exe => "python2.6")

那么,当您尝试时会发生什么?
>> RubyPython.start(:python_exe => "/usr/local/bin/pypy")
RubyPython::InvalidInterpreter: An invalid interpreter was specified.
    from /Library/Ruby/Gems/1.8/gems/rubypython-0.6.3/lib/rubypython.rb:67:in `start'
    from /Library/Ruby/Gems/1.8/gems/rubypython-0.6.3/lib/rubypython/python.rb:10:in `synchronize'
    from /Library/Ruby/Gems/1.8/gems/rubypython-0.6.3/lib/rubypython/python.rb:10:in `synchronize'
    from /Library/Ruby/Gems/1.8/gems/rubypython-0.6.3/lib/rubypython.rb:54:in `start'
    from (irb):4

很遗憾,它需要CPython 2.4-2.7。它不能与CPython 3.x、PyPy、Jython等一起使用。再次引用文档中的话:
RubyPython已经测试了基于C的Python解释器(cpython),版本为2.4到2.7。计划进行工作以支持Python 3,但尚未开始。如果您有兴趣帮助我们实现Python 3支持,请告诉我们。
不看代码,我猜rubypython是使用rubyffi来包装CPython嵌入API或直接通过其dll/so/dylib导出调用CPython VM内部。
如果是前者,这个项目可能可行,但仍需要大量工作。PyPy不支持CPython的嵌入式API。如果它有自己的嵌入式API,您可以潜在地重写rubypython的较低级别以包装那些API,而保留高级别代码不变。但是,嵌入PyPy仍然是一个正在进行中的工作(请参见http://mail.python.org/pipermail/pypy-dev/2012-March/009661.html,了解6个月前的情况)。因此,您需要首先帮助使PyPy嵌入准备好投入使用并稳定,然后将rubypython的较低级别移植到使用不同API。
如果是后者,你基本上没有机会了。PyPy永远不会支持CPython内部结构,而CPython的许多内部实际上是用RPython或Python编写的,然后为PyPy编译,因此原则上甚至不可能。您必须彻底重写所有rubypython的内容,找到一种使其工作的方法,而不仅仅是移植较低级别。

一个替代方案是将Ruby移植到RPython,并使用PyPy构建一个可以在更高层次上相互通信的Ruby解释器和Python解释器; 然后,编写类似于PyRuby和PyPy的rubypython之类的东西将变得微不足道。但是,第一步非常困难。


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