Миграция с CPython на Jython
Я подумываю о переносе моего кода (около 30K LOC) с CPython на Jython, чтобы я мог лучше интегрироваться с моим java-кодом.
Есть ли контрольный список или руководство, на которое я должен обратить внимание, чтобы помочь мне с миграцией? Кто-нибудь имеет опыт работы с чем-то похожим?
Из чтения сайта Jython, большинство проблем кажутся слишком неясными, чтобы беспокоить меня.
Я заметил, что:
- безопасность потоков - проблема.
- Поддержка Unicode кажется совсем другой, что может быть проблемой для меня.
- mysqldb не работает и нуждается в замене на zxJDBC
Что-нибудь еще?
Связанный вопрос: Каковы некоторые стратегии для написания кода Python, который работает в CPython, Jython и IronPython
Ответы
Ответ 1
Я начинаю это как вики, собранную из других ответов и моего опыта. Не стесняйтесь редактировать и добавлять материал, но, пожалуйста, старайтесь придерживаться практических советов, а не списка сломанных вещей. Здесь старый список различий с сайта Jython.
Управление ресурсами
Jython не использует подсчет ссылок, и поэтому ресурсы освобождаются, поскольку они
собираются мусор, что намного позже, чем вы увидите в эквиваленте
Программа CPython
-
open('file').read()
не закрывает файл автоматически.
Лучше используйте идиому with open('file') as fp
.
- Метод __ del __ вызывается очень поздно в коде Jython, а не сразу
после удаления последней ссылки на объект.
Интеграция MySQL
mysqldb
является c-модулем и поэтому не будет работать в jython. Вместо этого вы
должен использовать com.ziclix.python.sql.zxJDBC
, который поставляется в комплекте с Jython.
Замените следующий код 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
- Вы не можете выражать незаконные символы Unicode в Jython. Попытка
например
unichr(0xd800)
приведет к исключению и имеет литерал u'\ud800'
в вашем коде просто навредит.
Отсутствующие вещи
- Модули C недоступны, конечно.
- os.spawn * функции не реализованы. Вместо этого используйте subprocess.call.
Производительность
- Для большинства рабочих нагрузок Jython будет намного медленнее, чем CPython. Отчеты
что-то от 3 до 50 раз медленнее.
Основной
Проект Jython все еще жив, но не работает быстро.
список рассылки dev
имеет около 20 сообщений в месяц, и, похоже, всего около 2 разработчиков
комментируя код в последнее время.
Ответ 2
Во-первых, я должен сказать, что реализация Jython очень хороша. Большинство вещей "просто работают".
Вот несколько вещей, с которыми я столкнулся:
-
Модули C не доступны, конечно.
-
open ('файл'). read() не закрывает файл автоматически. Это связано с различием в сборщике мусора. Это может вызвать проблемы со слишком большим количеством открытых файлов. Лучше использовать "с открытым (" файлом ") как идиомой fp.
-
Установка текущего рабочего каталога (с использованием os.setcwd()) работает для кода Python, но не для кода Java. Он эмулирует текущий рабочий каталог для всех связанных с файлами, но может делать это только для Jython.
-
Разбор XML будет пытаться проверить внешний DTD, если он доступен. Это может привести к значительным замедлениям обработки кода обработки XML, поскольку парсер будет загружать DTD по сети. я сообщила об этой проблеме, но пока остается незафиксированной.
-
Метод __ del __ вызывается очень поздно в коде Jython, а не сразу после удаления последней ссылки на объект.
Существует старый старый список различий, но последний список недоступен.
Ответ 3
До сих пор я заметил еще две проблемы:
- Строка интернирования 'a' is '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 была бы простой, и я уверен, что они будут принимать патчи.
(Я делал то же, что и вы, перенося приложение недавно)
Ответ 4
Когда я переключил проект с CPython на Jython некоторое время назад, я понял скорость до 50x для критически важных секций. Из-за этого я остался с CPython.
Однако теперь это может измениться с текущими версиями.
Ответ 5
Вы также можете исследовать JPype. Я не уверен, насколько зрелым он сравнивается с Jython, но он должен позволить CPython получать доступ к Java-коду.
Ответ 6
Недавно я работал над проектом для профессора в моей школе с группой. Раньше было решено, что мы напишем проект в Python. Мы определенно должны были использовать CPython. Мы написали программу на Python, и все наши модульные тесты в конечном итоге сработали. Поскольку у большинства людей уже установлена Java на своих компьютерах, а не на Python, мы решили просто развернуть ее как банку Jython. Поэтому мы написали GUI с Swing, потому что это включено в стандартную библиотеку Java.
В первый раз, когда я запускал программу с Jython, она сразу же разбилась. Во-первых, csv.reader ".fieldnames" всегда казался None. Поэтому мне пришлось изменить несколько частей нашего кода, чтобы обойти это.
Также разбился другой раздел моего кода, который отлично работал с CPython. Jython обвинил меня в ссылке на переменную, прежде чем ей было назначено что-либо (что заставило меня с ума сойти, и на самом деле это было не так). Это один из примеров: Внешний вид рецепта ActiveState Code
Хуже того, производительность была ужасная. В основном этот код объединил несколько файлов CSV, один из которых составлял около 2 ГБ. В CPython он работал через 8,5 минут. В Jython он работал через 25 минут.
Эти проблемы произошли с 2.5.2rc2 (последним на момент написания этого сообщения).