Данная флеймообразующая статья призвана собрать в одном месте актуальную информацию по преимуществам Python над Ruby и Ruby над Python. Основываясь на собственном многолетнем опыте использования обоих языков, я постарался ограничить сравнение языками как таковыми и их стандартными библиотеками — сравнение web фреймворков, сред разработки и доступных библиотек не включены в статью, так как здесь и без меня немало копий сломано.
Начнем с Python, потому что по алфавиту
- Документация намного лучше, чем у Ruby. С вступительной частью, литературными отступлениями и многочисленными примерами. У Ruby многие модули, например DL или Win32API не документированы вообще, документация в целом значительно слабее.
- Используются настоящие потоки операционной системы. Несмотря на то, что оба языка используют GIL (global interpreter lock), использование настоящих потоков позволят коду на Python выполнять в отдельных потоках блокирующие операции — например, вызов shell скрипта или функций операционной системы — и при этом на блокировать другие потоки. В Ruby до версии 1.9 использовался один настоящий поток, а переключение между потоками языка эмулировалось. На практике это приводит к тому, что если в отдельном потоке Ruby вызвать shell скрипт (например, копирование файлов) или функцию операционной системы (например, показать окошко с сообщением) — то все остальные потоки в данном скрипте останавливались. Начиная с версии 1.9 Ruby использует настоящие потоки операционной системы, но на данный момент (версия 1.9.3-p125) множество недоработок не позволяют получить от этого преимущество — в частности, Ruby крайне не любит поднимать GIL при вызовах блокирующих операций, так что попытка показать окно операционной системы в отдельном потоке так же остановит остальные — на этот раз потому, что не будет поднят GIL.
- Поддержка unicode — в Ruby она появилась только начиная с версии 1.9, процесс перехода на которую пока далек от завершения.
- Поддержка именованных аргументов функций. В Ruby данный подход можно эмулировать, передав последним аргументом словарь, но это увеличивает количество кода.
- Очень хорошая встроенная библиотека ctypes для взаимодействия с операционной системой. Встроенная в ruby библиотека dl намного хуже документирована и сложнее в использовании — авторы рекомендуют использовать gem 'ffi'.
- Функция является объектом — ссылку на нее можно поместить в переменную, массив, передать другой функции. В ruby идентификатор функции сам по себе является вызовом, поэтому для передачи ссылки на функцию ее нужно оборачивать в промежуточный объект, «proc», что усложняет код.
- Поддержка декораторов — возможность добавлять к объектам аннотации, меняющие их поведение. В ruby это можно эмулировать с помощью интроспекции — но код становится сложнее, требует велосипеда с этой самой интроспекцией, которая еще и не очень быстрая.
- Встроенная поддержка JSON. В ruby — только начиная с версии 1.9
- Встроенная поддержка SQLite. Ruby не имеет встроенных средств работы с базами данных.
- Встроенный GUI, «Tk», одинаково хорошо поддерживается на всех платформах. В Ruby тоже есть Tk, но инсталлятор для Windows по умолчанию его не ставит, а в OSX начиная с 10.6 он не работает для поставляемого с системой Ruby и нужно его перекомпилировать, что в целом не очень просто.
- В Ruby исключение, брошенное не в главном потоке, не обрабатывается обработчиком исключений по умолчанию.
- Поддержка распаковки и запаковки архивов в стандартной библиотеке.
- Хорошая поддержка GUI библиотеки Qt для всех поддерживаемых платформ. А Qt, это, как известно — сила.
- Поддерержка named capture groups в регулярных выражениях. В Ruby — только начиная с версии 1.9
- В целом более распространен. Если у какой-ниубдь программы или библиотеки есть binding (VirtualBox, Qt, GTK) то в большинстве случаев это будет Python.
- Стабильные версии 2.6 и 2.7 почти не отличаются друг от друга и являются мейнстримом, переход на 3.x — в очень отдаленной перспективе. У Ruby сейчас активно идет переход с несовместимых веток 1.8 на 1.9 — довольно болезненный, мучительный и порождающий косяки.
Возникло впечатление, что Python лучше? Смотрим со стороны Ruby
- Интерполяция строк позволяет включать в строки код на Ruby, автоматически подставляя в строку результат его выполнения.
- Встроенная поддержка openssl. Для python — либо использовать ActivePython с не очень удобной и слабо документированой реализацией pyopenssl, либо самому ставить более удобную m2crypto — которая не то чтобы особо легко ставится, особенно под windows.
- Поддержка создания внутренних DSL: блоки, instance_eval, вызов функции без скобок.
- Удобный механизм вызова shell команд и получения результата их работы — всего два символа `. Корректно работает с путями, содержащими пробелы — чего не скажешь о модуле subprocess в Python, где для корректной работы с пробелами приходится передавать команду и ее аргументы не строкой, а списком.
- Возможность включать модули по относительному пути. Python технически это может, но большим количеством кода и с рядом неприятных спецэффектов.
- Встроенная поддержка OLE в Windows. В Python есть хороший модуль pyWin32 — но его надо либо устанавливать вручную, либо устанавливать ActivePython, где он идет в комплекте.
- Индексирование за пределами коллекции возвращает nil, что позволяет в ряде случаев писать очень лаконичный код.
- Удобный синтаксис подавления ожидаемых ошибок.
- Начиная с версии 1.9 можно указать кодировку текстового файла при его открытии.
- В стандартную библиотеку входит неплохой шаблонизатор «erb».
- Возможность создания временных папок с автоматическим удалением. В Python такая возможность появилась только в версии 3.2 — а это совсем отдаленное будущее.
- Есть языковая конструкция switch. А в python — нету.
- Начиная с версии 1.9 named capture groups в регулярных выражениях можно автоматически превращать в переменные.
- Лучшая поддержка работы со временем и датой. Стандартная библиотека Python даже с UTC не позволяет работать.
- Чтение содержимого файла в Windows без спецэффектов. В Python файл по умолчанию открывается в «текстовом режиме», что автоматически конвертирует переводы строки и обрывает чтение при достижении волшебного символа EOF, что может привести к неприятным багам.
- У потоков есть метод exit, который позволяет штатно остановить работу потока снаружи. В Python остановить работу потока «снаружи» нельзя — нужно встраивать собственные велосипеды с флагом остановки.
Выводы
Сверяемся со списком и выбираем язык под задачу. Ruby традиционно лучше справляется с обработкой текста, DSL, автоматизацей shell (смотрим на rake и завидуем). Python — многопоточность, GUI, биндинги ко всему что движется, лучшая документация и поддержка индустрией. При использовании Ruby, если есть возможность, лучше использовать версии 1.9.x — там слишком много изменений к лучшему по сравнению с 1.8.x. Вопросы, комментарии, флейм? Добро пожаловать в комменты.
P.S. Предвидя комментарии вида «а мне для <пункт сравнения> больше нравится <язык>, потому что <причина>». На вкус и цвет фломастеры разные, я рассказываю с колокольни своего практического опыта и моих задач, которые, к тому же, далеки от сайтостроения. В статье описаны различия, которые я расставил как «сильные» и «слабые» стороны исключительно на свой субъективный, хотя и профессиональный, взгляд. Надеюсь, статья станет неким базисом, на основании которого разработчики смогут выбрать язык под свои задачи чуть более осознанно.
P.P.s Предвидя комментарии вида «в <пункт сравнения> код на <язык> написан неправильно — это делается по другому». Примеры утрированы и сравнивают одинаковые возможности языков, без учета лучших практик их применения. Исключительно в целях предотвратить распухание статьи. Хочется быть компактным.
Автор: eyeofhell