Переход с CPython на Jython

Я подумываю о переносе моего кода (около 30K LOC) с CPython на Jython, чтобы я мог лучше интегрироваться с моим Java-кодом.

Есть ли контрольный список или руководство, на которое я должен обратить внимание, чтобы помочь мне с миграцией? Есть ли у кого-нибудь опыт делать что-то подобное?

После прочтения Сайт Jython большинство проблем кажутся слишком неясными, чтобы меня беспокоить.

Я заметил, что:

  • безопасность потоков - проблема
  • Поддержка Unicode выглядит совсем иначе, что может быть проблемой для меня.
  • mysqldb не работает, его нужно заменить на zxJDBC

Что-нибудь еще?

Связанный вопрос: Каковы стратегии написания кода Python, работающего в CPython, Jython и IronPython?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
24
0
4 340
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Пока что я заметил еще две проблемы:

  • Интернирование строки '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 была бы простой, и я уверен, что они будут принимать патчи.

(Я делал то же самое, что и вы, недавно портировал приложение)

Как я знаю, "is" нужно использовать только для проверки, хранятся ли объекты в одном и том же месте в памяти. Использование «is» вместо «==» - плохая привычка.

Alex Bolotov 16.04.2009 01:13

о да, в этом вы правы. Но не забывайте про «is None» / «is not None», это немного отличается от случая «is-same-object», который вы описываете, это больше похоже на «is-null» (я думаю).

shylent 17.10.2009 22:13

@shylent: "None" (т.е. null на других языках) является одноэлементным (источник: docs.python.org/c-api/none.html)

Hut8 17.12.2010 00:16

Когда я некоторое время назад переключил проект с CPython на Jython, я понял, что для критичных по времени секций скорость снижена до 50 раз. Из-за этого я остался с CPython.

Однако это могло измениться сейчас с текущими версиями.

Говоря в 2015 году, я бы сказал, что это все еще проблема. И выполнение, и запуск Jython болезненны. Но против этого вы должны противопоставить яркость идеи Jython. Есть (очевидные) стратегии: писать критичные ко времени вещи прямо на Java, использовать CPython для начального запуска и тестировать новые биты, не связанные с какими-либо классами Java. Священным Граалем, по-видимому, является беспроблемная интеграция CPython-Jython ...

mike rodent 22.05.2015 08:45

Прежде всего, я должен сказать, что реализация Jython очень хороша. Большинство вещей «просто работает».

Вот несколько вещей, с которыми я столкнулся:

  • Модули C, конечно, недоступны.

  • open ('file'). read () не закрывает файл автоматически. Это связано с разницей в сборщике мусора. Это может вызвать проблемы со слишком большим количеством открытых файлов. Лучше использовать идиому «with open ('file') as fp».

  • Установка текущего рабочего каталога (с помощью os.setcwd ()) работает для кода Python, но не для кода Java. Он эмулирует текущий рабочий каталог для всего, что связано с файлами, но может делать это только для Jython.

  • Синтаксический анализ XML попытается проверить внешний DTD, если он доступен. Это может вызвать значительное замедление кода обработки XML, поскольку синтаксический анализатор будет загружать DTD по сети. У меня сообщил об этой проблеме, но пока не исправлено.

  • Метод __ del __ вызывается в коде Jython очень поздно, а не сразу после удаления последней ссылки на объект.

Есть старый список отличий, но недавний список недоступен.

О методе __del__: спецификация на самом деле не определяет, когда именно метод должен быть вызван, поэтому вам вообще не следует полагаться на него в своем коде. (Я считаю, что где-то в документации Python есть уведомление об этом.)

Sasha Chedygov 06.04.2010 00:41

Вы также можете изучить JPype. Я не уверен, насколько он зрелый по сравнению с Jython, но он должен позволить CPython получать доступ к Java-коду.

Недавно я работал над проектом для профессора в моей школе с группой. Вначале было решено, что мы будем писать проект на Python. Нам определенно стоило использовать CPython. Мы написали программу на Python, и все наши модульные тесты в итоге заработали. Поскольку у большинства людей на компьютерах уже установлена ​​Java, а не Python, мы решили просто развернуть ее как Jython jar. Поэтому мы написали графический интерфейс с помощью Swing, потому что он включен в стандартную библиотеку Java.

Когда я впервые запустил программу с Jython, она сразу же вылетела. Во-первых, csv.reader's ".fieldnames" всегда казался None. Поэтому мне пришлось изменить несколько частей нашего кода, чтобы обойти это.

Также произошел сбой в другом разделе моего кода, который отлично работал с CPython. Jython обвинил меня в том, что я ссылаюсь на переменную до того, как ей что-либо было присвоено (что сводило меня с ума, но на самом деле это не так). Это один из примеров: Внешняя сортировка рецепта кода ActiveState

Что еще хуже, спектакль был ужасным. В основном этот код объединял несколько файлов CSV, один из которых был около 2 ГБ. В CPython он работал за 8,5 минут. В Jython он работал за 25 минут.

Эти проблемы произошли с 2.5.2rc2 (последней на момент написания этого поста).

Ответ принят как подходящий

Я начинаю это как вики, собранную из других ответов и моего опыта. Не стесняйтесь редактировать и добавлять материалы, но, пожалуйста, старайтесь придерживаться практических советов, а не списка сломанных вещей. Вот старый список отличий с сайта 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 на ?.

Юникод

  • В Jython нельзя использовать недопустимые символы Юникода. Пробовать что-то например, unichr(0xd800) вызовет исключение, а наличие буквального u'\ud800' в вашем коде просто нанесет ущерб.

Пропавшие вещи

  • Модули C, конечно, недоступны.
  • Функции os.spawn * не реализованы. Вместо этого используйте subprocess.call.

Представление

  • Для большинства рабочих нагрузок Jython будет намного медленнее, чем CPython. Отчеты что-нибудь от 3 до 50 раз медленнее.

Сообщество

Проект Jython все еще жив, но не так быстро развивается. В список рассылки разработчиков имеет около 20 сообщений в месяц, и кажется, что разработчиков всего около 2 совершающий код в последнее время.

Другие вопросы по теме