从Python迁移到Jython

时间:2009-01-07 15:46:10

标签: python migration jython cpython

我正在考虑将我的代码(大约30K LOC)从CPython移动到Jython,这样我就可以更好地与我的java代码集成。

我应该查看一份清单或指南,以帮助我进行迁移吗?有没有人有做类似事情的经验?

从阅读Jython site开始,大多数问题都显得过于模糊,无法打扰我。

我注意到了:

  • 线程安全是一个问题
  • Unicode支持似乎有很大不同,这对我来说可能是一个问题
  • mysqldb不起作用,需要用zxJDBC替换

还有别的吗?

相关问题:What are some strategies to write python code that works in CPython, Jython and IronPython

6 个答案:

答案 0 :(得分:10)

首先,我不得不说Jython的实现非常好。大多数事情“只是工作”。

以下是我遇到过的一些事情:

  • 当然,C模块不可用。

  • open('file')。read()不会自动关闭文件。这与垃圾收集器的区别有关。这可能会导致打开文件过多而导致问题。最好使用“with open('file')作为fp”idiom。

  • 设置当前工作目录(使用os.setcwd())适用于Python代码,但不适用于Java代码。它模拟了与文件相关的所有内容的当前工作目录,但只能为Jython执行此操作。

  • 如果外部DTD可用,XML解析将尝试验证外部DTD。这会导致XML处理代码大量减速,因为解析器将通过网络下载DTD。我reported this issue,但到目前为止它还没有固定。

  • __ del __方法在Jython代码中很晚才被调用,而不是在删除对象的最后一次引用后立即调用。

有一个old list of differences,但最近的列表不可用。

答案 1 :(得分:8)

到目前为止,我已经注意到另外两个问题:

  • 字符串实习'a'是'a'不能得到保证(这只是CPython上的实施侥幸)。这可能是一个严重的问题,而且实际上是我移植的一个库(Jinja2)。单元测试(一如既往)是你最好的朋友!
Jython 2.5b0 (trunk:5540, Oct 31 2008, 13:55:41)
>>> 'a' is 'a'
True
>>> s = 'a'
>>> 'a' is s
False
>>> 'a' == s   
True
>>> intern('a') is intern(s)
True

这是关于CPython的同一个会话:

Python 2.5.2 (r252:60911, Oct  5 2008, 19:24:49)
>>> 'a' is 'a'
True
>>> s = 'a'
>>> 'a' is s
True
>>> 'a' == s
True
>>> intern('a') is intern(s)
True

  • os.spawn *函数未实现。而是使用subprocess.call。我真的很惊讶,因为使用subprocess.call的实现很简单,我相信他们会接受补丁。

(我最近做了类似的事情,最近移植了一个应用程序)

答案 2 :(得分:5)

我是从其他答案和我的经验中收集的维基开始的。随意编辑和添加内容,但请尽量坚持实用的建议,而不是一堆破碎的东西。这是来自Jython网站的old list of differences

资源管理

Jython不使用引用计数,因此资源被释放 垃圾收集,这是你在相同的时间看到的 CPython计划

  • open('file').read()不会自动关闭该文件。 更好地使用with open('file') as fp成语。
  • __ del __方法在Jython代码中很晚才被调用,而不是立即调用 在删除对象的最后一次引用之后。

MySQL集成

mysqldb是一个c模块,因此无法在jython中使用。相反,你 应该使用与Jython捆绑在一起的com.ziclix.python.sql.zxJDBC

替换以下MySQLdb代码:

connection = MySQLdb.connect(host, user, passwd, db, use_unicode=True, chatset='utf8')

使用:

url = "jdbc:mysql://%s/%s?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull" % (host, db)
connections = zxJDBC.connect(url, user, passwd, "com.mysql.jdbc.Driver")

您还需要将所有_mysql_exception替换为zxJDBC

最后,您需要将查询占位符从%s替换为?

的Unicode

  • 你不能在Jython中表达非法的unicode字符。尝试一下 像unichr(0xd800)一样会导致异常,并且有一个文字u'\ud800' 在你的代码中只会造成严重破坏。

遗失的东西

  • 当然,C模块不可用。
  • os.spawn *函数未实现。而是使用subprocess.call。

效果

  • 对于大多数工作负载,Jython将比CPython慢​​得多。报告是 任何比较慢3到50倍的东西。

社区

Jython项目仍然存在,但不是快速移动。该 dev mailing list 每个月大约有20条消息,而且似乎只有大约2个开发者 最近提交代码。

答案 3 :(得分:3)

前段时间我将项目从CPython切换到Jython时,我意识到时间关键部分的速度降低了50倍。因此,我留在CPython。

但是,现在版本可能已经改变了。

答案 4 :(得分:3)

您可能还想研究JPype。我不确定它与Jython相比有多成熟,但它应该允许CPython访问Java代码。

答案 5 :(得分:2)

最近,我和一个小组一起为我学校的一位教授做了一个项目。在早期,我们决定用Python编写项目。我们绝对应该使用CPython。我们用Python编写了程序,所有的单元测试最终都有效。因为大多数人已经在他们的计算机上安装了Java而不是Python,所以我们决定将其部署为Jython jar。因此,我们使用Swing编写了GUI,因为它包含在Java的标准库中。

我第一次使用Jython运行该程序时,它立即崩溃了。首先,csv.reader的“.fieldnames”似乎总是为None。因此,我不得不更改代码的几个部分来解决这个问题。

我的代码的另一部分也崩溃了,它与CPython一起运行良好。 Jython指责我在变量被分配之前引用变量(这让我疯了,实际上并非如此)。这是一个例子:ActiveState's Code Recipe's external sort

更糟糕的是,表现糟糕。基本上这段代码组合了几个CSV文件,其中一个大约是2 GB。在CPython中,它在8.5分钟内运行。在Jython中,它在25分钟内运行。

这些问题发生在2.5.2rc2(撰写本文时的最新内容)。