Framework — В чём смысл противостояния Python vs Ruby


Содержание

В чем принципиальная разница RoR и Python (Django)?

После работы на чистом «Си» решил для себя идти в дотНет направлении, но никак не получается, не выходит. Два дня назад было 9-тое собеседование в котором я понял что просто не тяну. Реально дотНет очень большой, всегда найдется момент о котором ты не знаешь на котором тебя обязательно поймают, после чистого «Си» этот C# имеет очень много всяких «финтифлюшек» в которых просто теряешься, не в обиду дотНетчикам но всякого мусора в C# просто навалом. Конечно я когда прошел кучу собеседований я познал много всяких тонкостей о которых не знал но всё равно, слишком много всего ! Я не знаю как там в Java но дотНет очень большая платформа, для меня это сложно, видать не тот мозг ! Уйду в Ruby или Python, хотя говорят что это для тех кто «неасилил» C#\Java наверно оно так и есть ! Последний надеюсь мой вопрос к вам коллеги : если строить web-приложение принципиальная разница есть между RoR или Python(Django) как по мне всё очень похоже! Спасибо всем, счастья, добра, удачи.

3 ответа 3

Важная ремарка. Данный ответ не является ответом на вопрос. Это еще один комментарий к ответу пользователя @Jarto. Пишу как ответ в силу того, что возможность комментировать вопрос пропала. Поэтому, если есть возможность, прошу перенести его в комментарии.

а чего такого в Ubuntu домохозяйкам не хватает-то?

@pirj начнем с того, что операционные системы используются не только домохозяйками. Это было лишь некоторое обобщение. Очень широкий сектор их использования — корпоративный. А потому помимо обычных пользователей (домохозяек, домохозяинов, студентов, пенсионеров и всех-все-всех) есть еще всяческие служащие, менеджеры, бухгалтеры, для которых компьютер является рабочим инструментом (не буду относить сюдя айтишников — среди них распространение линукса довольно велико, но они в отличие от служащих и просто пользователей не исчисляются сотнями миллионов)

Так вот. Почему же не Linux:

  1. MS Office. Да, я знаю, что есть Open Office, Libre Office и что-нибудь еще. Но главенствующую роль все же занимает именно продукт Microsoft, а все остальные, хорошо это или плохо, вынуждены под него подстраиваться. Даже если вы внутри своей компании полностью откажетесь от использования MS Office, заставить другие компании сделать то же самое вы не сможете. А уж обмен всяческой документацией между теми или иными компаниями, фирмами, ведомствами — дело самое обычное. Не будете же вы требоватьот какого-нибудь банка/налоговой/службы безопасности присылать вам документы в формате odt.
  2. Привычка. Отучить десятки миллионов пользователей от Windows и приучить к Linux — задача непростая. Даже если ваша супруга с ней может справиться, не факт, что с ней справятся сотни (или хотя бы десятки) миллионов других людей. Да, Ubuntu смогла повернуться лицом к пользователю, и не выглядит как эротическая мечта красноглазого линуксоида, но дьявол, как известно, кроется в деталях. А смириться с этими деталями многим непросто.
  3. Игры (не самая важная, но довльно значимая причина). Что бы там ни говорили про портирование Доты и всяческие похвальные начинания от Valve, Linux даже близко не является игровой осью. На нем нет ни одного классного и коммерчески успешного эксклюзива (если даже я ошибаюсь, то их единицы), те хорошие игры, что есть, являются в основном портами, и портируются в лучшем случае ненамного позднее их выхода на Win. И это при том, что Windows сама по себе не очень может похвастаться изобилием. Я уже не говорю про довольно хреновую ситуацию с драйверами видеокарт — насколько мне известно, производительность одних и тех же моделей видеокарт отличаются в худшую сторону на Linux по сравнению с их аналогами, работающими из-под Windows. Я уже не говорю, что всяческие конфигурации, когда на ноутбуке стоят встроенная и дискретная видеокарты, заставляют пользователя плясать с бубном, чтобы заставить работать дискретную карту.
  4. На большинство компьютеров при покупке уже предустановлена Windows. Является ли это происками злыдней из компании Макрософак, или карой Всевышнего за наши земные грехи, но это факт.
  5. Практически полное отсутствие рекламы. А она, как известно, двигатель торговли. Если спросить у не-айтишников, почему бы им не поставить Linux, подавляющее большинство из них ответит «А что это?»
  6. И наконец, самая главная причина. ЗАЧЕМ? Что такого сулит простому пользователю Linux, ради чего он сломя голову бросится его устанавливать? Как известно, от добра добра не ищут (даже если это «добро» — Windows). Пользователь в основной своей массе ленив, и ему это просто не нужно.

PHP vs Python vs Ruby для разработки веб-приложений: подробное сравнение

Адаптированный перевод этой статьи.

PHP, Python или Ruby-on-Rails (RoR): какой язык лучше для разработки веб-приложений в 2020 году?

Это один из наиболее обсуждаемых вопросов среди веб-программистов, студентов и компаний, интересующихся разработкой собственных сайтов. На самом деле, у каждого языка есть плюсы и минусы, преимущества и недостатки. Они полностью определяются вашими требованиями к разработке веб-приложений.

С помощью этого поста должны проясниться многие сомнительные моменты, связанные с этими языками программирования. Таким образом, вы сможете выбрать наиболее подходящий язык в соответствии со спецификой ваших потребностей и запросов. Детальный и всесторонний сравнительный анализ трёх наиболее популярных языков, а именно PHP vs Python vs Ruby (RoR), опираясь на статистические данные и данные по различных параметров. Итак, начнём поединок самых популярных языков программирования.

1. PHP vs Python vs Ruby: доля рынка

Статистические использования и рыночная доля любого языка программирования дают представление о его популярности среди масс. На изображении ниже показаны наиболее широко применяемые серверные языки программирования.

Победитель – PHP

2. PHP vs Python vs Ruby: сайты, созданные с их помощью

У PHP много известных клиентов, таких как Wikipedia, Facebook, PixelCrayons – и это только немногие из них. С другой стороны,

Ruby-on-Rails также обслуживает известных клиентов, в том числе Twitter, Hulu, Groupon, и т.д. И наконец, король поисковых систем Google, а также YouTube созданы на языке Python.

Победитель – «ничья»

3. PHP vs Python vs Ruby: юзабилити

Юзабилити – это один из важнейших факторов, влияющих на выбор языка программирования для разработки проекта вашего сайта. Практически все языки программирования формируют пользовательский интерфейс. Язык с высоким уровнем юзабилити делает возможной разработку более мощного, масштабируемого и высокопроизводительного программного обеспечения. Ниже приведена сравнительная характеристика юзабилити языков PHP, Python, и Ruby.

Победитель – Ruby-on-Rails (RoR)

4. PHP vs Python vs Ruby: кривая обучаемости

Простота обучения или «кривая обучаемости» — это ещё один важный параметр, который также учитывается при выборе языка программирования для профессионального роста или следующего проекта по разработке веб-приложений. Язык с высокими значениями кривой обучаемости лёгкий для понимания и содержит чистый исходный код. Из трёх рассматриваемых языков лучшая кривая обучаемости у Python, на втором месте PHP, на третьем — Ruby-on-rails.

Победитель — Python

5. PHP vs Python vs Ruby: сравнение популярности

Вне всякого сомнения, сегодня наиболее популярный в мире язык программирования – это PHP. Будучи одним из самых старых языков, PHP приобрёл много поклонников среди кодировщиков и большую клиентскую базу. Два других языка, т.е. Ruby и Python, относительно молодые, и, соответственно менее популярны в массах. На изображении внизу показан индекс TIOBE, который создан и поддерживается корпорацией TIOBE, основанной в Нидерландах. Индекс оценивает уровень популярности различных языков программирования.

Ниже интересное видео, в котором описывается преимущество PHP над Python при оценке уровня популярности:

Победитель — PHP

6. PHP vs Python vs Ruby: сравнение производительности

Производительность любого языка программирования имеет решающее значение. Высокопроизводительный язык позволяет создавать масштабируемое и быстродействующее программное обеспечение с высокой степенью защиты. На приведённом ниже изображении показаны средние значения времени исполнения и строки кодов каждого из трёх языков. По этим двум параметрам вы можете оценить и сравнить производительность рассматриваемых языков.

Победитель – Ruby и PHP

7. PHP vs Python vs Ruby: наиболее обсуждаемый язык

Самый обсуждаемый язык программирования может быть полезен во многих отношениях. Если какой-либо язык популярен или его активно обсуждают, он собирает большое сообщество пользователей, которое в кратчайшее время может помочь в решении вашего вопроса. Вместе с тем, наиболее обсуждаемый язык имеет хорошую поддержку. На изображении внизу приводится статистика популярности языков программирования.

Победитель — Python


8. PHP vs Python vs Ruby: наличие вакансий и размер заработной платы

Анализируя частоту объявлений о вакансиях по какому-либо языку, можно получить довольно полезную информацию. Если вы соискатель, вы сможете сделать выводы о большом выборе доступных вакансий по любому языку. С другой стороны, эта статистика важна для разработчиков сайтов и каждого, кто ищет идеальный язык программирования. Безусловно, язык с большим количеством вакансий предусматривает работу большого числа программистов и гарантирует стабильную занятость и хорошие перспективы развития карьеры.

Победитель — PHP

9. Дополнительная информация.

Рассмотрим другие важные данные об этих трёх языках:

10. PHP vs Python vs Ruby: «плюсы» и «минусы»

Для чёткого представления о серверных языках программирования PHP, Python или Ruby важно понимать их преимущества и недостатки. У каждого языка есть плюсы и минусы. Всё зависит от того, какие потребности и ожидания вы связываете с этими языками. Вы можете выбрать язык, наиболее отвечающий нуждам и потребностям вашей деятельности. Далее приведены плюсы и минусы каждого из трёх языков программирования.

PHP vs Python vs Ruby: преимущества

PHP Ruby Python
Бесплатное программное обеспечение по лицензии PHP Кроссплатформенность и открытый исходный код Лёгкий и быстрый в изучении
Лёгкий в освоении (высокая скорость обучения) Может быть встроен в язык разметки гипертекста Поддерживается множеством платформ и операционных систем
Крупное сообщество пользователей и разработчиков Язык программирования сверхвысокого уровня (VHLL) Читабельный и организованный синтаксис
Расширенная поддержка баз данных Простой и понятный синтаксис, позволяющий начинающему разработчику очень быстро изучить язык Обеспечение быстрого прототипирования и динамических семантических свойств
Предоставляет большое количество доступных расширений и исходных кодов Простое подключение к базам данных DB2, MySQL, Oracle и Sybase Огромное сообщество поддержки
Разрешает исполнение кода в ограниченных средах выполнения Созданные на Ruby большие масштабируемые программы просты в сопровождении Простое построение приложений путём тестирования и импорта необходимых функций
Предоставляется возможность управления нативными сессиями и расширения API Наличие встроенного отладчика и гибкого синтаксиса Реюзабилити (возможность повторного использования) за счёт тщательной разработки пакетов и модулей
Хорошая альтернатива конкурентам, таким как ASP (Active Server Pages) от Microsoft Возможность написания внешних библиотек на Ruby или C Объектно-ориентированный подход к программированию
Работает практически на любой операционной системе или платформе Возможность написания многопоточных приложений с простым API

PHP vs Python vs Ruby: недостатки

PHP Ruby Python
Не подходит для разработки настольных приложений Возможны трудности в изучении Недостаточно эффективная работа с многоядерными и многопроцессорными вычислительными системами
Традиционно скудный функционал для обработки ошибок Нехватка информационных ресурсов Ограниченный уровень доступа к базам данных
Глобальные параметры конфигурации могут менять семантику языка, осложняя процессы внедрения и совместимости Большие затраты процессорного времени (CPU time) по сравнению с другими языками Отсутствие коммерческой поддержки даже для Open Source проектов (однако, эта ситуация начинает меняться)
Обращение к объектам по умолчанию осуществляется методом «вызова по значению» (CallByValue), что противоречит аналогичным операциям для большинства языков и застаёт многих программистов врасплох Сравнительно медленная разработка обновлений Небольшое количество разработчиков Python по сравнению с другими языками, например с Java
В целом считается менее защищённым по сравнению с другими языками программирования По отзывам более медленный по сравнению с языками типа Java

Ниже представлено интересное видео на тему сравнения PHP, Python, и Ruby on Rails. Это видео многое прояснит для вас. Посмотрите его:

Заключение.

Приведённые выше факты и статистические данные помогут вам сделать правильный выбор языка программирования в соответствии с конкретными потребностями вашей деятельности.

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки

Вход Регистрация Donate FAQ Правила Поиск

PHP Zend Framework vs. Ruby on Rails

Заслуженный участник

26/07/09
1559
Алматы

У руби, имхо, больше гибкости — проще писать и, что самое главное, исправлять код (при наличии достаточного опыта и знаний). Особую роль здесь играют гипертрофированная динамическая типизация и прочие характерные примочки.

Ну а при хорошем знании Ruby, фреймворк Ruby on Rails почти идеально подходит для разработки именно web-софта, просто потому что создавался специально для этих целей.

А php вроде как ближе к «традиционному» алголообразному программированию. Если вы в основном пишете на C/C++/Pascal, то с php, конечно, будете чувствовать себя увереннее. К тому, же из-за некоторой его «низкоуровневости» (по сравнению с руби) при желании можно достичь большего контроля над проектом, управлять каждой мельчайшей деталью системы. Правда, при этом, значительные изменения дизайна/архитектуры приложения будут обходиться дороже (больше кода переписывать).

Кстати, есть мнение, что php в некотором смысле более стабилен. Речь идет в первую очередь о среде исполнения, конечно. Здесь и скорость больше и вообще мелкие технические вопросы проработаны немного лучше. Да и php-разработчиков (пользователей) больше.

Решать все равно вам. :)

Circiter
Спасибо!
Просто я хотел бы изучить и тот фрэймворк и тот, но не успел, а тут проект намечается. Конечно, не так велик, как я написал. И конечно, PHP я знаю лучше, с Ruby у меня и опыта-то нет. Но есть немного времени и желание впитать современность! Вот, стал слышать хорошие отзывы о RoR. Мне нравится «полная объектно-ориентированность» (точнее так — я считаю, что она либо должна быть, либо отсутствовать; а не вариант PHP), «быстрота разработки и элегантность кода», «масшатабируемость» Правда, я «сишник», и пока мне сложно понять элегантность кода, точнее, эстетичность. Но изучу я оба фрэймворка, но о проекте речь сейчас. А еще хочется увидеть, как нужно грамотно сравнивать.

Спасибо, хочется еще мнений!

P.S. Говорят, быстрее уже Ruby, якобы в 1.9 его основательно переписали. Не знаю.

Заслуженный участник

26/07/09
1559
Алматы

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

— Пн окт 11, 2010 07:35:24 —

По основной теме гляньте ещё вот эту ссылочку.

Заслуженный участник

26/07/09
1559
Алматы

Ну хорошо, а какие сайты написаны на ZF и RoR?


Ваш вопрос, скорее, надо было поставить так: писать ли сайт на Ruby или на Python. Советую всерьёз рассмотреть возможность написания сайта на Python, с задействованием фреймворка Django.

Из плюсов:
1. Питон относительно простой и в то же время универсальный язык. Изучив Питон, можно использовать его не только при создании сайтов, но и в математических рассчётах, создании графических приложений для Linux и Windows, смартфонов и т.п.
2. Большее, чем у Руби сообщество разработчиков. См. Tiobe Programming Community Index.
3. Код на Питоне легко читается, имеет значительно меньшую тенденцию к замусориванию. Я имею опыт создания движков крупных сайтов как на PHP, так и на Питоне. PHP это, совершенно однозначно, язык прошлого поколения. Удобство программирования на PHP и Питоне различается на порядок.
4. Наличие мощной системы по миграции с одной конфигурации Django на другую ( http://south.aeracode.org/ ).

Справедливости ради стоит отметить и минусы:
1. Плохая поддержка юникода. Это частично исправлено во фреймворке Django, но порой приводит к возникновению неожиданных проблем.
2. Я знаю, что у Руби есть какие-то уникальные особенности, которые упрощают разработку сайтов, которых нет и не может быть в Питоне. Подробнее сказать не могу, т.к. сам ничего на Руби не писал.
3. С регулярными выражениями в Питоне работать (по идее) менее удобно, чем в Руби.

Где используют Питон?
Для вычислений Python используется в Фермилабе, NASA, JPMorgan и т.п. Сайты, написанные на Питоне: YouTube, http://rasp.yandex.ru/ (написан на Django), http://afisha.yandex.ru/msk/ (написан на Django), http://blog.kremlin.ru/ (написан на Django), и т.д.

Простите что немного не по теме, но не могли бы Вы поконкретнее пояснить данную мысль? Или где почитать можно? Это именно вопрос, а не желание «лезть в бутылку» с моей стороны.

Дело в том, что я имею довольно большой опыт написания приложений на PHP5 + опыт программирования на компилируемых ЯВУ (с веб-разработками не связанных). Так как за время работы с PHP5 я находил его все более и более удобным, то мне интересна эта тема.

Возможно, конечно, что я просто уткнулся в то, что понравилось и мне элементарно не до чего-то, возможно, намного более хорошего.

Страница 1 из 1 [ Сообщений: 9 ]

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей

H C PHP на Python: о чем бы я хотел знать заранее в черновиках Перевод

Сегодня мы тут припозднились, но все-таки продолжаем развивать тему языка Python, по которому у нас готовится новая книга, и допечатывается широко известная. На сей раз мы хотели затронуть интересную тему перехода с PHP на Python, попутно рассмотрев некоторые фреймворки Python, поговорить о веб-разработке на этих языках и, конечно же, дать вам пищу для размышлений.

Приятного чтения и хороших выходных!

Что «говорят люди»

Программисты, имеющие мнение о том, как обстоят дела в Интернете, охотно высказываются и по поводу PHP. Время от времени кто-нибудь напишет такую филиппику, в которой расскажет, чем плох PHP, и почему все должны избегать этого языка. Вам посоветуют перейти на Java, Ruby, Python – на что угодно, только бы слезть с PHP. Хотя я не могу полностью осудить PHP, притом, что некоторое время назад по пояс увязал в импровизированной базе кода на этом языке, слова «красивый», «выразительный» и «поистине объектно-ориентированный» пробуждают во мне некие чувства, которые PHP решительно не удовлетворяет, при всех своих неловких и противоречивых попытках «исправиться».

Но когда я, наконец, перемахнул через забор и отправился туда, где трава зеленее, я ожидаемо обнаружил, что и на райском лугу кое-где попадаются проплешины. Более того, я обнаружил, что переход на другие языки означает для PHP-программиста серьезный сдвиг парадигмы. Поскольку я не видел, чтобы кто-нибудь уже об этом рассказывал, решил сам написать для вас эту путеводную статью.

Что же такое PHP?

Если вы начали карьеру веб-разработчика с языка PHP, как и я, то, вероятно, разделяете мои предубеждения о том, что представляет собой веб-разработка. Но давайте для начала выясним, что такое язык PHP.

В основе своей PHP – это система шаблонов. Вероятно, когда-то ее укусил радиоактивный паук, и она мутировала в массивный объектно-ориентированный язык – но, в сущности, так и осталась системой шаблонов. Смысл этого утверждения лучше всего прояснить на следующем примере: что происходит при обращении к PHP-документу в браузере?

  • Веб-сервер (например, Apache) получает запрос на PHP-документ
  • Веб-сервер запускает PHP, передавая запрошенный файл и некоторые детали о запросе
  • PHP обрабатывает запрошенный файл, дампит все «обязательные» или «включенные» файлы, а также интерпретирует разряды “ ”, когда они встречаются.
  • PHP возвращает интерпретированный документ (теперь уже на чистом HTML/XML/CSS т.д.) на веб-сервер, который отправляет его в браузер.

Вот почему можно записывать HTML прямо в PHP-файл (вне тегов), и он будет работать. В принципе, PHP – это HTML-файл (даже если в нем нет «сырого» HTML), доказательство тому – предварительная обработка документа перед выдачей.

Кроме того, PHP – своего рода минимальный фреймворк. Он оказывает вам кое-какие любезности (например, разбирает HTTP-запросы, преобразуя их в аккуратные массивы вроде $_GET и $_POST) и предоставляет гигантскую библиотеку дополнительных функций — например, для соединения с базой данных и обработки изображений.

Важно осознавать это и понимать, что PHP как таковой (без учета каких-либо сторонних аддонов или уровней абстрагирования) уже в готовом виде решал за веб-разработчика массу проблем. Эта поддержка временами была хороша, временами – не очень; но, в любом случае, проблемы редко решаются единственным способом. Легко принять за истину, что PHP решает задачи единственно верным, каноническим образом. Привыкните к тому, что это не так.

Плох, но не так уж плох.

Как я уже говорил, люди всегда будут клясть PHP — можете даже не сомневаться. Если вы в состоянии прочесть статью «PHP: фрактал некачественного проектирования», а затем с чистой совестью программировать на нем дальше – что ж, вы проявили твердость. У PHP действительно есть недостатки, от мелких прыщиков до серьезных структурных проблем.

Но, в конечном итоге, дело за вами, вашим софтом и пользователями вашего софта. Потенциальные недостатки PHP — пустая академическая мишура, пока не отражаются на этих трех китах; предположу, что в большинстве случаев действительно не отражаются. Не каждый пытается написать новое браузерное супер-пупер приложение, которое откроет путь к Web 3.0. Некоторые люди просто хотят автоматизировать простые операции у себя на персональном сайте, либо построить простую CRUD-систему для данных, которыми пользуются на работе. Не ведитесь на ненависть к PHP и не отказывайтесь от нормального инструмента, который вполне неплохо решал ваши проблемы, не требуя дополнительной настройки.

Что такое Python, и как написать на нем веб-приложение?

Python – универсальный язык программирования. В нем просто куча библиотек, и на этом языке можно решать самые разные задачи, но, в принципе, этот язык не затачивался под какие-либо конкретные цели.

Кроме того, работать с ним – одно удовольствие.

Однако он не является ни веб-фреймворком (даже минимальным), ни системой шаблонов. Если вы планируете применять Python для веб-разработки примерно столь же активно, как и PHP, то Python потребуется дополнить этими вещами.

Я упоминаю об этом, поскольку в мире PHP также есть свои фреймворки и системы шаблонов – например, Zend Framework или CakePHP. Лично я использовал CodeIgniter на двух-трех сравнительно крупных проектах, и нашел его очень полезным… поначалу. Поддерживая код (и совершенствуя непрерывную интеграцию) пару лет подряд, я разочаровался в этом фреймворке. Обнаружил, что все, что мне требовалось от фреймворка, на деле достигается при помощи пары сотен строк вспомогательных функций при условии аккуратного планирования структуры классов. Итак, мне «фреймворк» поначалу показался огромной пушкой для стрельбы по воробьям.

Если вы ощущали нечто подобное, то поймете, что в Python потребуется использовать фреймворк – хотя бы самый скромный – так как (напоминаю) вы уже привыкли к работе с минимальным фреймворком под названием PHP.

То же касается системы шаблонов. Сначала я думал, «люди, чего вы возитесь с этой системой шаблонов», но, в самом деле, если вы не фанат больших кусков HTML с «несинтаксической» подсветкой в своем логическом коде (наверняка не фанат!), то придется работать с системой шаблонов.

Итак, усвоив это, давайте рассмотрим некоторые фреймворки и системы шаблонов.

Едва подавшись в мир фреймворков Python вы немедленно окажетесь перед выбором, напоминающим обоюдоострый клинок. Фреймворков здесь – десятки, от минимальных и низкоуровневых до выраженно абстрагированных программных пакетов, прибамбасов в которых больше, чем на поясе у Бэтмена. Я работал всего с несколькими из них, поэтому остановлюсь на тех, которые знаю — примерно в том порядке, в котором я их изучал.

mod_python и серверные страницы python

Прежде, чем я «освоил» веб-разработку на Python, я, разумеется, рассматривал ее с точки зрения PHP-разработчика. Поэтому сразу проникся mod_python и серверными страницами Python (PSP). Такая конструкция позволяет работать с Python примерно так, как вы привыкли программировать на PHP: пишете сценарий, и Apache выполняет его в нужном месте, как только получит запрос GET или POST на этот сценарий. Данный сценарий может представлять собой как чистый Python, так и html-файл со встроенными PSP (в принципе, PSP – это система шаблонов, для работы с ней просто вставляете теги (с разделителем ), как привыкли делать в PHP).


На первый взгляд все кажется замечательным, но со временем вы осознаете, что практически не улучшили структуру и безопасность вашего приложения по сравнению с PHP, зато променяли все веб-ориентированные вкусности PHP на язык с чуть более (ладно, гораздо более) качественным синтаксисом. В общем, из пустого в порожнее, поэтому я никогда и не видел большой пользы в переходе на mod_python.
По-видимому, сообщества Python и Apache со мной согласны, так как в 2010 году проект mod_python был закрыт. Невелика потеря, скажу я вам.

Если произнести в переполненной комнате «Веб-фреймворк Python?» то, вполне возможно, они просто недоуменно на вас посмотрят, но если кто-то и ответит, то, вероятно, скажет: «Django». Некоторые считают Django единственным веб-фреймворком Python, достойным обсуждения.
Django – это полноценный фреймворк; в нем встроено практически все необходимое, и со всем этим сразу можно работать. Там есть и шаблоны, и абстракция базы данных/объектно-реляционное отображение, сеансы и безопасность и даже собственный веб-сервер.

Несмотря на многообразные возможности и популярность, Django мне не приглянулся по нескольким причинам:

Во-первых, мне в самом деле не импонирует работа в стиле «все, что вам когда-либо может понадобиться, у нас уже есть». Я предпочитаю более мелкие, модульные инструменты, при помощи которых могу легко выстраивать код.

Во-вторых, поскольку это один из тех фреймворков, где проект запускается при помощи специальной команды «init», которая выдает вам целое дерево сгенерированного кода, посреди которого вы пишете свое приложение. Возможно, я ошибаюсь, но по опыту такая ситуация чревата неудобными обновлениями, которые приходится точечно инъецировать в код приложения.

Наконец (и здесь я тоже могу ошибаться) мне показалось, что Django задумывался для управления структурой и кодом базы данных, поэтому не очень хорошо будет работать с имеющейся базой данных. Поскольку передо мной очень часто ставились задачи написать альтернативные клиентские интерфейсы или инструменты отчетности для готовых баз данных (зачастую доступных только для чтения), мне он не подходит.
Повозившись с Django несколько дней, я все бросил и вернулся к PHP.

После Django меня по нескольким причинам заинтересовал CherryPy. Во-первых, он не генерирует такого большого дерева трафаретного кода, а представляет собой просто библиотеку, которую нужно импортировать. Гораздо важнее, что он не привязан к конкретной системе шаблонов или уровню базы данных, поэтому вы можете использовать любые их варианты (или не использовать вообще). Знакомясь с ним, я все еще считал, что «не нужна мне никакая система шаблонов», а проект, за который я брался, вообще не имел отношения к базе данных. Поэтому такой минимальный фреймворк идеально мне подошел.

Мне удалось написать приятную утилиту, которой я до сих пор пользуюсь при работе, но ощущения остались противоречивые. Спишите это на мою неопытность в веб-разработке на Python, но, в целом, у меня возникли две проблемы с проектом на CherryPy:

  1. Существует как минимум два или три способа делать определенные вещи — например, настраивать конфигурационные опции, и документация свободно комбинирует эти способы. Один и тот же метод мог срабатывать, но не всегда; поэтому создавалось впечатление, что код мой противоречив.
  2. Многие вещи в программе требуют некой автомагической комбинации имен функций и переменных; такова, например, сеансовая аутентификация. Мне было очень сложно выполнить эту работу правильно, а отладочные сообщения не помогали.

Может быть, со временем и опытом, подробнее изучив документацию CherryPy, я бы его освоил, но в данном случае меня ждала срочная работа, которую пришлось делать на PHP.

Наконец, я открыл Flask. Подобно CherryPy, это простая библиотека, которую всего лишь нужно импортировать — и можно пользоваться любой системой шаблонов или уровнем базы данных, что вам приглянутся (хотя, складывается впечатление, что Flask хорошо интегрирован с jinja2). Пока Flask меня вполне устраивает, он более прямолинеен, чем CherryPy, без всей этой автомагии, связанной с именами функций и переменных. Мне пришлось попотеть над тем, как он анализирует данные из сложных форм (по-видимому, не любит вложенные массивы). Кроме того, он помог мне осознать собственную потребность в языке шаблонов, а также узнать практически все необходимое о Jinja2 буквально за десять минут.

Системы шаблонов Python

Не буду распространяться здесь о системах шаблонов, так как до сих пор мне доводилось использовать лишь Jinja2; но здесь хотелось бы дать совет таким же PHP-разработчикам, как и я, которые еще полагают, что не нуждаются в таких системах. Ребята, окажите себе услугу и начните работать с системой шаблонов. Помните, что PHP — в сущности, одна из них, поэтому не думайте, что раньше с такими системами не работали (работали, но просто не осознавали этого). Не поступайте так, как я в моем проекте на CherryPy, просто то есть, не записывайте ваш HTML прямо в строки и не используйте подстановку в стиле printf(). Да, это сработает, но будет сделано топорно, вы не получите правильной подсветки синтаксиса и смешаете представление с логикой.

Однако не пытайтесь выбрать какую-то определенную систему шаблонов. Все они почти одинаковы, только синтаксис отличается. Я выбрал Jinja2, так как она хорошо интегрируется с Flask и, по-видимому, довольно быстра. Но на самом деле с новой системой шаблонов можно разобраться за какие-нибудь полчаса.

Что мне особенно понравилось в системе Jinja2 (и у других систем шаблонов, вероятно, также есть такое свойство) — так это возможность наследовать от других шаблонов. Так, я могу создать базовый шаблон для всех страниц с определенными именованными блоками, затем сделать так, чтобы другие шаблоны наследовали от этого и могли добавлять конкретные блоки, которые им, возможно, потребуется изменить. В PHP все было сложнее: там приходилось создавать различные элементы страницы (заголовок, область навигации, контент), прибегая к функциям или методам класса.

Некоторые общие соображения, которые следует усвоить

Итак, вы подобрали для себя фреймворк и систему шаблонов, но остались определенные концепции, с которыми вы привыкли работать, а также вредные привычки, от которых вы хотите избавиться, чтобы писать веб-приложения на Python.

Веб-страница — не STDOUT

Если в PHP вы хотели что-нибудь вставить на веб-страницу, то просто делали эхо-запрос. Поскольку мы просто делаем препроцессинг документа на месте, все, изрыгнутое PHP, окажется на веб-странице. Это оптимальный стиль программирования на PHP, именно так там решаются проблемы с кодом. Признаться, многие PHP-разработчики и отладку выполняют именно так (применяя echo или var_dump() в произвольной точке кода, чтобы посмотреть, что там происходит).

Фреймворки Python, например, Flask или CherryPy, работают иначе. В них вы пишете функции, возвращаете фрагмент HTML, который фреймворк уже упаковывает в HTTP-отклик. Итак, в отличие от PHP, если вы «print» что-нибудь, то оно не окажется на итоговой веб-страницы, а отправится туда, куда уходит весь стандартный вывод.

Мне было несложно к этому адаптироваться, поскольку примерно так я и писал приложения на PHP: они у меня строились как наборы функций, возвращающих фрагменты HTML. Однако для некоторых PHP-программистов, привыкших запрашивать данные при помощи echo, такой подход покажется очень неестественным.

Выше я описывал, как сервер обрабатывает запрос к PHP-файлу. В принципе, если я перейду по ссылке http://example.com/lib/docs/help, веб-сервер попробует найти /lib/docs/help/index.(запрос). Если окажется, что “запрос” означает “php”6, то PHP получит файл, сделает свое дело, и все будут довольны. Если подходящего индексного файла не найдется, то вы получите ошибку 404, а может и 403. Короче говоря: если вы хотите обеспечить доступ к URL при помощи PHP (если не колдовать с настройками конфигурации веб-сервера, например, не писать mod_rewrite), то должны расположить PHP-файл по этому URL.

В современных фреймворках Python это делается иначе. Сделать конкретный URL, получив с сервера HTML-страницу в качестве отклика, можно и в том случае, когда фактически нужные файлы и не расположены по этому пути. Для таких случаев во фреймворке имеется система для отображения URL на функции или классы вашей программы. Обычно этот процесс называется «маршрутизацией».

Итак, чтобы в вышеприведенном примере сделать рабочий URL на сайте, написанном с применением фреймворка Python, можно не класть никаких файлов в /lib/docs/help, да и вообще не создавать эти директории под webroot. Просто организуйте, чтобы ваш код отображал путь ‘/lib/docs/help’ на функцию или класс, которые бы возвращали конкретный отклик (фрагмент HTML или, скажем, HTTP-объект).
Некоторые фреймворки PHP или приложения обеспечивают нечто похожее на такую маршрутизацию (вроде “pretty/simplified/clean URLS”), при этом обычно используется mod_rewrite, скрывающий запрос к конкретному php-файлу.

Прежде, чем я взялся за программирование веб-приложений на Python, я не так хорошо ориентировался в HTTP. Если вы просто работаете с PHP, то, вероятно, знаете, что информация может отправляться на сервер в виде запросов “GET” или “POST” и знаете, в чем разница между такими запросами, записанными в адресной строке. Оказывается, HTTP далеко не ограничивается GET и POST, и если вы работаете с Python, то весьма целесообразно понимать этот протокол целиком.

Дело не в том, что фреймворки Python не абстрагируют HTTP; просто они его абстрагируют иначе, нежели PHP – и, честно говоря, абстрагируют чище и естественнее. Например, тогда как PHP предоставляет содержимое HTTP-запроса вашему сценарию при помощи серии глобальных массивов (напр. $_GET, $_SERVER, т.д.) или вызовов функций (напр. getallheaders()), фреймворки Python обычно предоставляют вам тот или иной объект запроса, инкапсулирующий весь HTTP-запрос.

Если учесть, что фреймворки Python и приложение на нем обрабатывают многие вещи, которые PHP просто делегирует серверу, то вполне логично, что вам придется несколько плотнее познакомиться с HTTP; не пугайтесь. Чем больше я учусь, тем больше склоняюсь к мысли, что HTTP в самом деле проще той мешанины, в которую его абстрагирует PHP.

Если вы работали с одним или несколькими известными PHP-фреймворками (напр., с CodeIgniter), то, вероятно, встречали термин «MVC». MVC – это стратегия проектирования ПО, при которой ваше приложение четко подразделчется на три части:

Модель – это ваша модель данных, обрабатывающая все операции считывания/записи данных, связанные с базой данных или хранилищем данных.

Представление – это интерфейс, который видит конечный пользователь и с которым он, собственно, работает.

Контроллер, обеспечивающий взаимодействия между представлением и моделью.

Если вы не работали с фреймворком или уже освоили паттерн MVC, то вас ждет шок. У меня сложилось впечатление, что фреймворки Python практически навязывают идею MVC на том или ином уровне. В конечном итоге, это положительно скажется на вашем коде, а без использования таких паттернов становится сложно масштабировать реальное приложение. Однако здесь придется немало изучить, если вы привыкли просто запихивать запросы к базе данных и бизнес-логику между большими кусками HTML по мере необходимости.

Планирование и проектирование

Да, «реальные программеры» здесь могут немного поморщиться, но если вы собираетесь расстаться с PHP, то должны привыкнуть, что теперь придется уделять больше внимания планированию веб-приложения. Если PHP в чем-нибудь и прекрасен, то именно в том, что позволяет сесть в кресло и написать что-то масштабное без особой предварительной подготовки. Просто вставляете код там, где он должен прийтись кстати.
Фреймворки Python, с которыми мне приходилось иметь дело, подходят к этому вопросу строже. Это не PHP, где вы просто ломитесь через сценарий сверху вниз; поэтому здесь вы не можете просто произвольно определять что заблагорассудится и рассчитывать, что эти вещи окажутся в области видимости, как только они вам потребуются. Аналогично, язык шаблонов – это просто язык шаблонов, а не полноценный язык программирования. Нельзя просто так поместить в шаблоне кучу вызовов функций и операций присваивания переменных лишь потому, что вам так нравится.

Кроме того, в таких фреймворках как Flask используются многие паттерны проектирования и абстрактные конструкции, назначение которых отнюдь не очевидно для людей, не изучавших всерьез теорию программирования. Чтобы правильно задействовать эти конструкции, требуется на более абстрактном уровне представить себе, что именно делает ваше приложение.


В конечном итоге, это пойдет вам на пользу, поскольку придется проектировать более качественные и аккуратные приложения, чем, возможно, получились бы у вас на другом языке. Но это предполагает абсолютно новый образ мышления и подход к работе.

Кроме необходимости переключиться на новую парадигму, которую я описал выше, Python имеет и некоторые характерные недостатки, проявляющиеся при веб-разработке. Думаю, было бы честно упомянуть здесь о них.

Чтобы развернуть приложение на PHP, достаточно лишь сбросить файлы .php в каталог под webroot. Развернуть приложение на Python несколько сложнее, это можно сделать несколькими способами, и у каждого из них есть свои достоинства и недостатки, которые необходимо взвесить.
Разумеется, ваш веб-хост может не поддерживать Python, Flask или любые другие библиотеки Python, требуемые для работы вашего приложения.

Доступ к базе данных

Если вы хотите углубиться в высокоуровневые абстракции, извлекающие из вашего кода весь противный SQL и заменяющие его объектами и вызовами методов, то Python покорит вас своими слоями ORM, например, SQLAlchemy. Если мы с вами единомышленники, и вы предпочитаете писать собственный SQL, то ситуация немного меняется.

В PHP есть приятный уровень абстрагирования базы данных, так называемый PDO, и если вы его еще не используете – прекратите набивать “mysql_” и используйте. PDO – это единая библиотека с согласованными классами, методами и свойствами, не зависящая от конкретного драйвера базы данных, который вы используете.

В свою очередь, Python обладает DB-API — это спецификация, описывающая создание библиотек для работы с базами данных в Python. Вместо библиотеки с драйверами для различных баз данных Python предоставляет библиотеки, специфичные для каждого продукта, которые (в основном) соответствуют DB-API. Теоретически все должно идти столь же гладко, как и с PDO, но на практике ситуация более разношерстная. Некоторые библиотеки расширяют DB-API дополнительными функциями, а сама спецификация гибко описывает, как должны реализовываться те или иные вещи (например, стиль параметров для параметризованных запросов). Мне это показалось неудобным, когда (например) я портировал Flask-приложение, написанное для psycopg2 (популярная библиотека PostgreSQL) на cx_Oracle (единственная библиотека Oracle, соответствующая DB-API) и бы вынужден корректировать кучу кода из-за различий в интерпретации спецификации.
Разумеется, можно было бы использовать ORM…

Акцент на программировании приложений

По-видимому, такие фреймворки как Flask или CherryPy предполагают, что вы пишете именно приложение, а не случайный набор произвольного веб-контента. Это отлично, если вы действительно пишете приложение, но ведь так бывает не всегда. Иногда просто пишется страница, перед отображением которой требуется выполнить какие-либо вычисления, либо форму, перед отправкой которой нужна какая-то простая обработка.
Если, допустим, вы ведете сайт с блогом, содержащим несколько разделов с контентом, почти не связанных друг с другом, причем большая часть контента унаследована и трогать ее не требуется, то PHP как раз вам подойдет. Если вы собираетесь добавить новую страницу, никак не связанную с остальным сайтом, но требующую предварительной обработки (например, просмотреть каталог MP3-файлов и отобразить информацию ID3 information), то достаточно написать новый .php-файл и положить его в каталог.

Если бы мой сайт управлялся приложением на Python, все было бы сложнее. Мене пришлось бы либо написать и развернуть новое приложение WSGI (слишком много работы ради одной страницы), либо добавить в имеющееся приложение новую функцию (усложнив, а, возможно, и дестабилизировав весь сайт).

Нужно ли переходить?

Я не из тех блоггеров, которые стали бы вас убеждать перейти с PHP на Python или на какой-нибудь другой язык. PHP в обозримом будущем никуда не денется, для многих приложений он совершенно адекватен. Но я скажу, что время, потраченное на изучение языка вроде Python, а также на освоение его популярных фреймворков, пойдет на пользу любому веб-программисту.

На самом деле, я дозрел до перехода на Python, когда стал все активнее прибегать к AJAX и обнаружил, что мои проекты превращаются из наборов динамических страниц в приложения на JavaScript, которые время от времени связываются с сервером для считывания и записи данных. Иными словами, когда мой серверный код чаще стал передавать вызовам AJAX операции чтения и записи в базу данных, нежели генерировать целые страницы отформатированного HTML, мне стало удобнее работать с фреймворками Python.

Рекомендую не расставаться с PHP в следующих случаях:

Ваши страницы состоят в основном из HTML и лишь кое-где содержат немного динамического контента.
Ваша работа будет развертываться на дешевом разделяемом веб-хостинге
Вы считаете, что пишете не «приложение», а просто «веб-страницы»

Если вы всерьез занимаетесь веб-разработкой и сами контролируете свой сервер, то следующий большой проект стоит написать на Python. Очень вероятно, что многие задачи по унаследованным проектам вы так и будете решать на PHP; но работу с Python стоит постоянно наращивать.

Python против Ruby

Я вижу, как люди, использующие Ruby, сильно критикуют Python на Stackoverflow. Это немного грустно, потому что Python и Ruby обычно самые лучшие друзья. Итак, я хотел бы поговорить не о том, кто из них лучший, а о том, каковы объективные различия.

Найти эту объективность было труднее, чем я думал, но я многому научился. И, как и предполагалось, многие из различий являются лишь семантическими, как например Ruby использует атрибут @, а Python атрибут self. И конечно объективно невозможно ответить, какой язык лучше, наверное, тот, который больше Вам знаком. И это не удивительно. А удивительно то, что существует немного различий, которые могут характеризовать тот или иной язык как лучший или худший. Даже те особенности языка, которые, казалось, «объективно хороши», в большинстве случаев оказываются делом вкуса.

Вот различия, которые я смог найти, и которые можно объективно назвать отличительными:

1. Ruby имеет ссылку на класс в теле класс

Это означает, что возможен следующий код:

Тогда как в Python вы должны написать:

Как Вы видите, практическое различие очень небольшое. Но вариант Ruby проще для понимания, поскольку «магия» заключается в определении класса, и смотря на класс, вы видите, что это выполняется. И действительно компонентная архитектура Zope использует некоторую «тяжелую магию» с метаклассами, чтобы сделать то же самое в Python:

Так что получить тот же самый эффект можно (В Python 2) с помощью нескольких умных уловок. В Python 3 нельзя, но не, потому что отличается синтаксис метакласса, а поэтому что в Python 3 вы вместо этого должны использовать декораторы. И что вы думаете проще

является снова вопросом вкуса. Итак, небольшое преимущество здесь без сомнения за Ruby. Но это действительно не очень важное преимущество, потому что вызов метода инициализации после класса или в качестве декоратора не является основным недостатком.

2. Ruby имеет continuations

Continuations — это «тяжелая магия». У Ruby они есть, а у Python нет. Вы можете «подделать» их, и, кажется, что многие из случаев употребления могут быть заменены с помощью ввода переменных в .next (), это вы можете сделать в Python 3.1. Использование Continuations кажется скорее ограниченным, и трудно поддающимся пониманию, но это есть как в Ruby, так и в Python. Так что еще один плюс для Ruby.

3. Python имеет генераторы

Вы можете подделать их в Ruby с помощью блоков или Continuations. Поэтому снова небольшое преимущество, но так или иначе небольшой плюс для Python , поскольку генераторы Python являются и простыми и понятными.

4. Python имеет множественное наследование

Некоторые люди утверждают, что множественное наследование является злом. Но его наличие означает, что, если вы считаете это злом, то не пользуйтесь им. Я много раз пользовался им, и никогда не встречал никаких проблем, но я думаю, что адаптация — лучший образец. Однако, весьма очевидно, что это плюс для Python.

5. Python имеет docstrings

Docstrings позволяют приложить документацию непосредственно к классам и методам. Это, конечно же, плюс для документации, и это позволяет таким функциям, как например, функция помощи переводчикам Python, быть действительно полезными. Еще один плюс.

Иии. вот и все!

Эти пять небольших отличий являются единственными объективными улучшениями, которые я смог увидеть, по отношению к другому языку. И как Вы видите, ни одно из них не является действительно значимым. Это лишь мелкие детали, от которых зависит только удобство работы. Итак, не перейти ли мне на Ruby прямо сейчас, когда я знаю, что он почти также хорош? Нет. Поскольку есть много других различий, различий в подходах и семантике. И к тому же мне больше нравится Python. Вот три основных функции Ruby, которые, по моему мнению, являются, либо непредусмотренными, либо не имеющими большого значения:


1. Ruby имеет встроенный regexp и line input looping

Язык Perl позволяет написать скрипт, который просматривает текстовые файлы построчно. В большинстве случаев это чрезвычайно полезно. Также Ruby, как говорят, лучше пишет glue.scripts, так что он больше подходит для замены shell-скрипта чем Python. Плюс для Ruby? Нет, только не для меня. Я это иногда делаю, главным образом в awk. Если они становятся более сложными, то я предпочитаю использовать ясность Python, чем неясность regexps. И иметь небольшой open(filename).readlines () не является столь уж большой проблемой. Так что я думаю, что эта функция лишь добавляет суеты, и я рад, что ее нет в Python. Ничего себе! Это превратилось уже в субъективную проблему! Меня это удивило.

2. Ruby защищает атрибуты класса и т.д.

Ruby рассматривает имена переменных, первая буква которых заглавная, как константы, поэтому вы не можете изменить их. Python не защищает ваш код от других программистов. Если они захотят создать вам проблем, они смогут это сделать. Мне это нравится. Я вспоминаю, когда я использовал Delphi, и мне надо было переместить в подкласс объект в стандартную библиотеку, а некоторые атрибуты или методы были защищены, то я не мог это сделать. Мне пришлось прекратить дублирование почти целого класса компонентов (или большинство) в мой подкласс, только потому, что разработчик основного класса не предусмотрел мой тип или требование. Так что такой вид защиты обычно является лишь проблемой. Таких проблем меньше в Ruby, поскольку он позволяет вам добавлять класс, но это еще большой плюс для Python по моему мнению. Я уверен, что люди, пользующиеся Ruby, не согласятся со мной. И это снова субъективно.

3. Ruby имеет блоки

Но некоторые различия, это больше различия в подходах, чем что-либо еще. Например, Ruby имеет концепцию блоков. Блоки, кажется, в значительной степени являются замыканиями, которым присвоено имя, и эта абстрактная концепция, в основном означающая часть кода, который получает переменные откуда-нибудь еще и может иметь локальные переменные, которые не забивают пространство имен.

Блоки Rubys широко пропагандировались (приверженцами Ruby) как нечто фантастическое по сравнению с Python. Но оказалось очень трудным найти случаи, когда Ruby действительно делал что-то чище, чем Python благодаря блокам. Ок, но оказывается, что в Python тоже есть блоки. Но их называют «функциями». В чем различие? Функции необходимо названии, а блокам нет. На этот счет программист Python сказал бы “Ага, так что блоки это лямбды!” Да, за исключением того, что блоки могут быть многострочным кодом и выполнять все, в то время как лямбды Python должны быть выражениями.

OK, итак один плюс Ruby? Нет. Поскольку, какая польза от блока, если вы не прикрепляете его к имени переменной, так чтобы можно было вызвать его? В Ruby вы создаете блоки и используете их непосредственно вот так:

Это в основном как у Python

Который конечно выполняется также и в Ruby. Какой способ аккуратнее? И снова это дело вкуса. Становится еще труднее принять решение, если учесть, что Ruby имеет специальное утверждение для вызова блока с параметрами. Он называется yield. Yield также присутствует и в Python, но там он используется для генераторов. Но мы получаем эти примеры кода:

Которые подозрительно похожи на

Поэтому, в конечном счете, можно сказать, что этот хваленый принцип блоков кажется очень редко в действительности приводит к какому-либо значительно отличающемуся от Python коду. Так что эти широко обсуждаемые различия в принципах в конечном итоге … являются (почти) одинаковыми!

4. Python легко работает со списками

Здесь стоит упомянуть, что у Python есть несколько важных функций, которых нет у Ruby, как например легкость работы со списками.

Но хотя я пользуюсь ими все время, потому что они практичны, я не знаю, что я о них думаю. Ок, это короче чем:

Но действительно ли это чище и удобнее для чтения? Я не уверен. Это снова становится вопросом вкуса . Мне не понравились list comprehensions, когда они впервые появились в Python, но конечно теперь я стал пользоваться ими. Так что это не очень хороший аргумент в пользу Python. И это снова субъективно.

5. Python имеет декораторы

Декораторы интереснее, чем другие способы сделать то же самое в Python, например вышеупомянутый initialize_magick (класс). Но опять-таки можно утверждать, что синтаксис @decorator лишь делает Python уродливым, и они вам не настолько нужны в Ruby. И снова это дело вкуса.

Итак, почему Python?

Итак, в конце концов, почему я субъективно предпочитаю практически во всем Python, а не Ruby? За ясность и простоту Python, за его принципы и подходы. В Ruby можно расширить любой класс. В Python, вы можете «примешивать» расширения в любой класс. В чем разница? В Python это является уродливым подходом, и его осуждают. В Ruby, многие примеры кода расширяют класс Array.

В Ruby, нет функций, но есть методы, блоки и лямбды. Все из них, кажется, имеют незначительные различия, а иногда необходимо вызывать функцию по имени, а иногда, используя функцию call(). В Python, есть только функции. Лямбды являются функциями whose __name__ is . Методы являются функциями, которые направлены на то, что вам не придется обходиться самостоятельно. Просто и ясно.

Python является более четким. В Ruby Вы можете опустить () при запросе метода. Сторонникам Ruby нравится это, потому что это заставляет запрос выглядеть как утверждение. Сторонники Python, подобно мне, думают, что это плохая идея заставлять запрос выглядеть подобно утверждению. Если это запрос, то он и должен так выглядеть.

Пакеты и модули Python намного лучше для пространства имен, чем модули Ruby. Снова субъективно. И вы можете выбирать, хотите ли вы импортировать в Python или нет. В Ruby это все, что вы можете сделать

И все это то, что заставляют меня говорить “Ээээ… ” о Ruby и “Да! ” в отношении Python, который отличается не конкретными функциями, а лишь субъективными опциями семантики языка и подходами. Действительно верно, что ни один из Языков не является лучше другого.

Разбираемся с устройством асинхронных фреймворков для Python

Содержание статьи

Асинхронные приложения — это типичный пример того, про что говорят «Новое — это хорошо забытое старое». Ну да, сам по себе подход появился еще очень давно, когда надо было эмулировать параллельное выполнение задач на одноядерных процессорах и старых архитектурах. Но песок — плохая замена овсу, «асинхронность» и «параллельность» — довольно-таки ортогональные понятия, и один подход задачи другого не решает. Тем не менее асинхронности нашлось отличное применение в наше высоконагруженное время быстрых интернет-сервисов с тысячами и сотнями тысяч клиентов, ждущих обслуживания одновременно. Возможно, стоит разобраться получше, как это все работает?

Зачем нужна асинхронность?

Если спуститься почти на самый низ, к ядру операционной системы, то у программиста, откровенно говоря, есть только два варианта работы с сокетом — синхронный и асинхронный.

С синхронным в целом все понятно — пришел клиент, открылся сокет, передали данные, если это все — сокет закрылся. В этом случае пока мы не закончили локальный диалог с одним клиентом — не можем начать его с другим. По такому принципу обычно работают простые серверы, которым не надо держать сотни и тысячи клиентов. В случае если нагрузка возрастает, но не критично — можно создать еще один или несколько потоков (или даже процессов) и обрабатывать подключения еще и в них. Это обкатанный годами, стабильно работающий подход, который, например, использует сервер Apache, — никаких неожиданностей, данные от клиентов обрабатываются в порядке строгой очереди, а в случае запуска какого-то «долгого» кода — например, каких-то вычислений или хитрого запроса в БД — это все никак не влияет на других клиентов.

Но есть проблема: сервер — это не Лернейская гидра, он не может плодить потоки и процессы вечно — есть же, в конце концов, вполне ощутимые ресурсы, которые тратятся при каждом таком действии, и имеется верхний порог использования этих ресурсов. И вот тогда все вдруг вспомнили про асинхронность и системные вызовы для неблокирующего ввода-вывода. Зачем плодить кучу сокетов и потоков, выедать ресурсы, если можно данные от многих клиентов сразу одновременно слушать на одном сокете?

Все началось с системных вызовов

Собственно, вариантов системных вызовов для неблокирующей работы с сетевым вводом-выводом не так уж и много (хотя они слегка и разнятся от платформы к платформе). Самый первый, базовый, можно сказать ветеран — это системный вызов select(), который появился еще в бородатые восьмидесятые годы вместе с первой версией того, что сейчас называется POSIX-сокетами (то есть сокетами в понимании большинства современных серверных систем), а тогда называлось Berkeley sockets, сокетами Беркли.

По большому счету, во времена описания системного вызова select() вообще мало кто задумывался о том, что когда-то приложения могут стать НАСТОЛЬКО высоконагруженными. Фактически все, что этот вызов умеет делать, — принимать фиксированное количество (по умолчанию не более 1024) однозначно описанных в программе файловых дескрипторов и слушать события на них. При готовности дескриптора к чтению или записи запустится соответствующий колбэк-метод в коде.

Почему select() все еще существует и используется?

Ну, во-первых, он существует именно потому, что существует, как бы каламбурно это ни звучало, — select() поддерживается практически всеми мыслимыми и немыслимыми программными платформами, которые вообще подразумевают сетевое взаимодействие. А во-вторых, есть, скажем так, «городская легенда», что в силу простой, как топор, реализации этот системный вызов на части архитектур (к которым не относятся ни широко используемые персональные компьютеры, ни даже серверы) обладает феноменальной точностью обработки тайм-аутов (вплоть до наносекунд). Возможно, при работе в области космических исследований или ядерной энергетики это спасет чью-то жизнь? Кто знает.


Потом кто-то задумался о том, что неплохо бы все-таки научиться делать действительно по-взрослому высоконагруженные сетевые приложения, и появился системный вызов poll(). Кстати, в Linux он существует довольно давно, а вот в Windows его не было до выпуска Windows Vista. Вместо разрозненных сокетов этот вызов принимает на вход структуру со списком дескрипторов (фактически произвольного размера, без ограничений) и возможных событий на них. Затем система начинает в цикле бегать по этой структуре и отлавливать события.

Главный минус вызова poll() (хотя это, несомненно, был большой шаг вперед по сравнению с select()) — обход структуры с дескрипторами с точки зрения алгоритмики линеен, то есть осуществляется за O(n). Причем это касается не только отслеживания событий, но и реакции на них, да еще и надо передавать информацию туда-обратно из kernel space в user space.

А вот дальше в каждой операционной системе решили пойти своим путем. Нельзя сказать, что подходы конкретно различаются, но все-таки реализовать кросс-платформенную асинхронную работу с сокетами в своей программе стало чуточку сложнее. Под Windows появился API работы с так называемыми IO Completion Ports, в BSD-системах добавили механизм kqueue/kevent, а в Linux, начиная с ядра 2.5.44, стал работать системный вызов epoll. Отлов асинхронных событий на сокетах (как бы тавтологично это ни звучало) стал асинхронным сам по себе, то есть вместо обхода структур операционная система умеет подавать сигнал о событии в программу практически моментально после того, как это событие произошло. Кроме того, сокеты для мониторинга стало можно добавлять и убирать в любой момент времени. Это и есть те самые технологии, которые сегодня широко используются в большинстве сетевых фреймворков.

Зоопарк event loop’ов

Основная идея программирования с использованием вышеописанных штук состоит в том, что на уровне приложения реализуется так называемый event loop, то есть цикл, в котором непосредственно происходит отлов событий и дергаются callback’и. Под *nix-системами давненько уже существуют обертки, которые позволяют максимально упростить работу с сокетом и абстрагировать написанный код от низкоуровневой системной логики. Например, существует известная библиотека libevent, а также ее младшая сестра libev. Эти библиотеки собираются под разные системы и позволяют использовать самый совершенный из доступных механизмов мониторинга событий.

Я буду приводить в пример большей частью пакеты для сетевого программирования на языке Python, ибо их действительно там целый зоопарк на любой вкус, а еще они популярны и широко используются в различных проектах. Даже в самом языке довольно давно уже существуют встроенные модули asyncore и asynchat, которые, хоть и не умеют работать с epoll (только select/poll), вполне подходят для написания своих реализаций протоколов.

Одна из проблем сетевых библиотек заключается в том, что в каждой из них написана своя имплементация event loop’а, поэтому, даже несмотря на общий подход, перенос, скажем, плагина для Twisted (Reactor) на Tornado (IOLoop) или наоборот может оказаться вовсе не тривиальной задачей. Эту проблему призван решить новый встроенный модуль в Python 3.4, который называется asyncio и, вопреки расхожему мнению, не является сетевой библиотекой или веб-фреймворком в полном смысле слова, а является именно что встроенной в язык реализацией event loop’а. Эта штука как раз и призвана сплотить сторонние библиотеки вокруг одной общей стабильной технологии. Если хочется немного подробностей и независимых впечатлений об asyncio — милости прошу сюда.

Для Tornado уже существует реализация поддержки event loop’а из asyncio, и, более того, она не так давно вышла из состояния беты. Посмотреть можно здесь. Для Twisted релиз asyncio тоже не оказался неожиданностью, и его разработчики даже написали своеобразный шутливый некролог для проекта, в котором, напротив, уверяют, что это вовсе не конец, а очень даже начало новой эпохи развития.
Если говорить уж совсем откровенно, то понятие асинхронного ввода-вывода необязательно должно относиться именно к сетевому сокету. Системы семейства *nix следуют принципу, согласно которому взаимодействие фактически с любым устройством или сервисом происходит через file-like объект. Примерами таких объектов могут служить UNIX-сокеты или, скажем, ноды псевдофайловой системы /dev, через которые осуществляется обмен информацией с блочными устройствами. Соответственно, говоря об event loop’ах, мы можем подразумевать не только сетевое взаимодействие, но и просто любой асинхронный I/O. А чтобы было что потрогать руками — советую глянуть, например, вот на этот встроенный модуль из Python 3.4.

Запутанная история

В современном мире фреймворк Twisted выглядит таким своеобразным мамонтом, legacy-архаизмом, который впитал в себя все попытки предоставить удобный интерфейс для написания сетевых приложений. Тем не менее интерфейс получился действительно удобный, с реализацией отложенного выполнения кода и прочими плюшками, когда никакого Node.js еще не существовало и в помине.

Как я уже упомянул выше, реализация event loop’а в Twisted называется Reactor. Суть работы с ним состоит в том, что мы регистрируем callback’и, которые выполняются в глобальном цикле в виде реакции на какие-то события. Выглядеть это может, например, так:

Причем, даже если внутри callback возникнет исключение, то реактор все равно продолжит работать, после того как залогирует трейсбэк и запустит зарегистрированные обработчики ошибок.

Кстати, нельзя не уточнить, что Twisted по умолчанию однопоточный, то есть вся эта развесистая петрушка реализована на внутренней магии вокруг системных вызовов для асинхронного I/O. Но на случай крайней нужды в нем есть и своя реализация ThreadPool, которая добавляет возможность работы нескольких потоков.

Сюда идет Tornado

Если Twisted все-таки представляет собой больше сетевую библиотеку, чем веб-фреймворк, то c Tornado все ровно наоборот. Этот пакет был разработан теми же товарищами, которые делали FriendFeed, — а это, на минуточку, реально высоконагруженный веб-проект с миллионами посетителей в день. Отличие выражается еще и в том, что в нем есть небольшой встроенный шаблонизатор и поддержка всяких «интернетных» технологий вроде работы с куками и генератора HTTP-ответов в разных форматах.
Кстати, Tornado появился немного раньше, чем в Python появилась встроенная поддержка epoll (обертки вокруг сетевых системных вызовов находятся в модуле select), поэтому он поставляется с небольшой библиотекой для этого вызова, написанной в несколько строчек кода на C в виде импортируемого модуля. Эта обертка используется на старых версиях Python, но, говорят, в некоторых случаях специально руками собранный с ней пакет работает чуточку быстрее, чем на ванильной реализации. Да, еще одна городская легенда.

Twisted возник на горизонте раньше Tornado, однако тогда еще не начался этот бум на асинхронные веб-приложения, а когда он все-таки пришел, то Twisted оказался слегка не у дел в этой сфере, потому что изначально смотрел немного в другую сторону. Это выразилось в том, что веб-приложения на Twisted сейчас в основном пишут только приверженцы старой школы, а для Tornado появилось довольно большое число библиотек, которые добавляют, например, асинхронную работу с базами данных и key-value хранилищами, удобную интеграцию с фронтенд-технологиями наподобие SockJS и SocketIO и все такое прочее. В результате он сейчас является прямым конкурентом Node.js, только из мира Python.

В качестве примера асинхронного подхода рассмотрим такой код:

Про то, что такое корутины и как они работают, можно прочитать в моей статье в октябрьском номере. Этот код можно считать примером простейшего асинхронного приложения на Tornado — запускается сервер на 9999-м порту, который при заходе по URL «/test» запускает отложенную таску, в которой каждую секунду шлет следующее число из счетчика в сокет, при этом не забывая обрабатывать другие подключения.

Освещаем события

Асинхронные серверы — это круто, но как же насчет асинхронных клиентов? Такие тоже писать довольно легко. В Python это можно делать с использованием одной из двух довольно известных библиотек — gevent и eventlet. На их основе создаются отличные скоростные парсеры и системы мониторинга, которые по-настоящему быстро опрашивают тысячи серверов.

Нет, на самом деле серверы с их помощью тоже можно писать. Например, в известной облачной open source платформе OpenStack eventlet используется как база при построении REST-сервисов в некоторых подпроектах. Но в этих библиотеках также присутствует действительно хорошая инфраструктура для написания клиентов.

Gevent работает в основном с библиотекой libevent (или, в новых версиях, libev), а eventlet может при желании работать и просто с epoll. Основная задача этих модулей — создание удобной инфраструктуры для работы с корутинами и запуск тасков в «зеленом» режиме, то есть реализация кооперативной многозадачности за счет быстрого переключения контекста.

Например, в eventlet есть механизм манкипатчинга стандартной библиотеки Python, который позволяет при использовании, скажем, модуля threading, подменять потоки на корутины. То есть в общем случае написанная в многопоточном стиле программа становится асинхронной.

В качестве примера кода с переключением контекста приведу код из примеров стандартной библиотеки gevent:

А вот первый же пример простейшего асинхронного клиента на eventlet (его и другие примеры можно найти на официальном сайте):

Основной и главной проблемой этих модулей можно назвать то, что в силу их завязанности на код на C и хитрости реализации их до сих пор в нормальном виде не портировали ни на PyPy, ни на Python 3, есть только прототипы.

И что в итоге?

С одной стороны, асинхронный подход к программированию крайне полезен при решении целого ряда задач, особенно в сфере веб-разработки. С другой — он зачастую требует вывернуть мозг наизнанку, так как любая непродуманная строчка кода может привести к блокировке всего и вся. Но, несомненно, знание того, как работают подобные вещи, может быть очень полезным для современного разработчика, особенно в свете развития таких языков, как Go и Erlang, которые внутри себя скрещивают сразу несколько видов асинхронности и многопоточности в одном флаконе. Поэтому — категорически рекомендую пробовать, ошибаться, радоваться и вообще программировать. Удачи!

PHP vs Ruby vs Python

Тема в разделе «Таверна», создана пользователем asdqwwerty, 08 Mar 2020 в 22:12 .

Оценить пост #

asdqwwerty

После того как я выучил HTML + CSS + JS(поверхностно) передо мной стал вопрос. Что же учить дальше? Очень хотел бы услышать мнение знающих людей (уверен тут есть такие), какой из языков сейчас наиболее актуален/будет актуален в скором будущем. Какой из них легче/сложнее? Так же слышал о Node.js поясните за него, ибо слышал очень хвалебные отзывы о нем. В общем ваше мнение на эту тему.
Забыл добавить. Интересует веб-отрасль.

Epicroy

firth

солянка кая то. учи жава и лисп.
питон — скриптовый язык, юзается везде.
пхп — язык веба, нужен для всяких там баз данных.
руби — это ваще диалект перла, очень специфичен
нод — это фреймворк серверной части.
зайди на хабр, потусуйся там.
помимо всего прочего, в каждом языке есть куча фреймворков, которые надо учить


Python vs Ruby: как язык программирования влияет на вашу работу

Набирающий популярность на Западе рекрутинговый сервис Workshape.io, соединяющий разработчиков и стартапы, проанализировал профили зарегистрированных пайтонистов и рубистов на предмет того, как выбор языка программирования влияет на работу. dev.by публикует сокращённый перевод публикации.

Один из потрясающих результатов создания Workshape.io — доступ к нестандартным данным, которые могут рассказать нам о том, чего мы иначе не узнали бы. Когда мы просим наших пользователей описать желаемую работу с распределением времени на задачи, мы можем не только собирать и сегментировать первичную информацию, но и представлять её в таком виде, в котором раньше её никто не видел.

В этом исследовании мы обратили взоры на некоторые из основных языков программирования, на которых держится весь Open Source. В частности, мы хотели сравнить два из них — Python и Ruby. Все мы знаем технические и философские различия между Python, Ruby, PHP и всеми остальными [языками], но как эти различия влияют на людей, которые ими пользуются? Влияет ли выбор языка программирования на то, как вы проводите рабочее время?

Для этого исследования мы взяли профили пользователей, которые выбрали Python или Ruby в графе «Желаемые технологии». Выше на диаграмме Венна видно, что на нашей платформе девелоперы чаще отдают предпочтение языку Python.

Мы сравнили эти две группы по уровню квалификации, набору вторичных навыков и, конечно, по распределению времени на универсальные аспекты разработки ПО. И вот, что выяснили.

Распределение по уровню квалификации

На Workshape.io мы собираем у пользователей информацию о желаемом уровне квалификации на следующей работе. Как видно из диаграммы выше, у нас предусмотрены четыре уровня квалификации.

По нашему определению, уровень Mid-weight можно присвоить разработчику, который считается полноценным членом команды, которому доверяют выполнение качественной работы без необходимости всесторонней поддержки. Этот уровень указали как желаемый на следующей позиции большинство пайтонистов.

Senior в нашем определении — опытный программист, которому можно доверить решения, влияющие на работу системы, и в обязанности которого входит курирование молодых сотрудников. Большинство рубистов указали этот уровень как желаемый на следующей позиции.

Мы не делаем далекоидущих заключений, но можем предположить, что рубисты более склонны думать о карьере, статусе в команде или необходимости большей автономии на следующей позиции.

Вторичные навыки

Анализ вторичных навыков (технологий, отличных от Python или Ruby, указанных программистами в нашем эксперименте) доказал вездесущность JavaScript. Эта технология оказалась наиболее популярной как среди разработчиков на Python, так и у сторонников Ruby. Ряд навыков встречается также в обеих группах: несмотря на то, что разработчики обычно предпочитают один язык другому, их сопутствующие навыки, в основном, похожи.

Распределение вторичных навыков

Python-разработчики больше склоняются к работе с бэкендом и технологиями нижнего уровня. В свою очередь Ruby-разработчики больше ориентированы на веб и мобильные разработки. Python-разработчики чаще интересуются машинным обучением и Data Science. Ruby-разработчики работают больше с Javascript-фреймворками.

На иллюстрации не показано, что Chef — самый популярный инструмент для управления конфигурацией среди Ruby-разработчиков, а эксперты Python в основном пользуются Ansible.

Стек технологий

В последней части исследования мы изучили использование стека технологий рубистами и пайтонистами в расчёте на рабочее время. На инфографике выше видно, что несмотря на разницу двух языков, общее распределение времени, посвящённого работе со стеком основных технологий, примерно одинаково.

Разница между Python и Ruby подкрепила наши данные по распределению навыков их носителей.

  • В обоих случаях разработчики в основном хотят уделять больше времени бэкенд-разработке.
  • Обе категории разработчиков уделяют примерно одинаковое внимание архитектуре, процессам, просмотру кода и документации.
  • Пайтонисты больше склоняются к Data (разница — 7%) и хотят уделять немного больше времени анализу.
  • Рубисты больше сосредоточены на фронтенд и, похоже, в большей степени интересуются TDD и BDD.

Заключение

В этом исследовании мы обнаружили и подтвердили некоторые интересные факты о разработчиках на Python и Ruby.

Python — более распространённый язык в нашей выборке, Ruby-разработчики составляют примерно 2/3 от числа пайтонистов. Есть чёткое разделение этих двух навыков: всего 15 процентов пайтонистов указали Ruby в качестве дополнительного навыка, 20 процентов рубистов сделали то же в отношении Python.

Медианный уровень квалификации для Python-разработчиков — Mid-weight (средний), для Ruby — Senior (старший). Учитывая субъективность и ограниченность выборки, мы не будем делать выводы относительно причин такого результата.

Навыки и временная нагрузка подтверждают, что Python больше связан с Data Science, чем Ruby. Ruby же имеет больше общего с веб-технологиями с сильным уклоном во фронтенд, а также с iOS.

Why is Ruby/Rails or Python/Django better than PHP?

a VWMsy d g bztf b fo y Zcg aF J OQDN e QIs t FK B X r WZ a vDkeK i qkIY n DFjj s AXQNo

Answer Wiki

Like Gidi Meir Morris says, comparing PHP to a framework is a bit problematic. A more accurate comparison would be to compare PHP to Python or Ruby, and to compare a framework like CakePHP to Rails or Django.

PHP, as a language, has a bad reputation for three main reasons:

  1. PHP is INCREDIBLY easy to pick up. In part because the language is designed that way, but also because there is a lot of documentation for PHP targeting people that doesn’t know anything about programming and should not ever be taught anything about programming. :) This is my favourite example: WPDesigners guide «So you wan.

(more) Loading…

Разбираемся с устройством асинхронных фреймворков для Python

Содержание статьи

Асинхронные приложения — это типичный пример того, про что говорят «Новое — это хорошо забытое старое». Ну да, сам по себе подход появился еще очень давно, когда надо было эмулировать параллельное выполнение задач на одноядерных процессорах и старых архитектурах. Но песок — плохая замена овсу, «асинхронность» и «параллельность» — довольно-таки ортогональные понятия, и один подход задачи другого не решает. Тем не менее асинхронности нашлось отличное применение в наше высоконагруженное время быстрых интернет-сервисов с тысячами и сотнями тысяч клиентов, ждущих обслуживания одновременно. Возможно, стоит разобраться получше, как это все работает?


Зачем нужна асинхронность?

Если спуститься почти на самый низ, к ядру операционной системы, то у программиста, откровенно говоря, есть только два варианта работы с сокетом — синхронный и асинхронный.

С синхронным в целом все понятно — пришел клиент, открылся сокет, передали данные, если это все — сокет закрылся. В этом случае пока мы не закончили локальный диалог с одним клиентом — не можем начать его с другим. По такому принципу обычно работают простые серверы, которым не надо держать сотни и тысячи клиентов. В случае если нагрузка возрастает, но не критично — можно создать еще один или несколько потоков (или даже процессов) и обрабатывать подключения еще и в них. Это обкатанный годами, стабильно работающий подход, который, например, использует сервер Apache, — никаких неожиданностей, данные от клиентов обрабатываются в порядке строгой очереди, а в случае запуска какого-то «долгого» кода — например, каких-то вычислений или хитрого запроса в БД — это все никак не влияет на других клиентов.

Но есть проблема: сервер — это не Лернейская гидра, он не может плодить потоки и процессы вечно — есть же, в конце концов, вполне ощутимые ресурсы, которые тратятся при каждом таком действии, и имеется верхний порог использования этих ресурсов. И вот тогда все вдруг вспомнили про асинхронность и системные вызовы для неблокирующего ввода-вывода. Зачем плодить кучу сокетов и потоков, выедать ресурсы, если можно данные от многих клиентов сразу одновременно слушать на одном сокете?

Все началось с системных вызовов

Собственно, вариантов системных вызовов для неблокирующей работы с сетевым вводом-выводом не так уж и много (хотя они слегка и разнятся от платформы к платформе). Самый первый, базовый, можно сказать ветеран — это системный вызов select(), который появился еще в бородатые восьмидесятые годы вместе с первой версией того, что сейчас называется POSIX-сокетами (то есть сокетами в понимании большинства современных серверных систем), а тогда называлось Berkeley sockets, сокетами Беркли.

По большому счету, во времена описания системного вызова select() вообще мало кто задумывался о том, что когда-то приложения могут стать НАСТОЛЬКО высоконагруженными. Фактически все, что этот вызов умеет делать, — принимать фиксированное количество (по умолчанию не более 1024) однозначно описанных в программе файловых дескрипторов и слушать события на них. При готовности дескриптора к чтению или записи запустится соответствующий колбэк-метод в коде.

Почему select() все еще существует и используется?

Ну, во-первых, он существует именно потому, что существует, как бы каламбурно это ни звучало, — select() поддерживается практически всеми мыслимыми и немыслимыми программными платформами, которые вообще подразумевают сетевое взаимодействие. А во-вторых, есть, скажем так, «городская легенда», что в силу простой, как топор, реализации этот системный вызов на части архитектур (к которым не относятся ни широко используемые персональные компьютеры, ни даже серверы) обладает феноменальной точностью обработки тайм-аутов (вплоть до наносекунд). Возможно, при работе в области космических исследований или ядерной энергетики это спасет чью-то жизнь? Кто знает.

Потом кто-то задумался о том, что неплохо бы все-таки научиться делать действительно по-взрослому высоконагруженные сетевые приложения, и появился системный вызов poll(). Кстати, в Linux он существует довольно давно, а вот в Windows его не было до выпуска Windows Vista. Вместо разрозненных сокетов этот вызов принимает на вход структуру со списком дескрипторов (фактически произвольного размера, без ограничений) и возможных событий на них. Затем система начинает в цикле бегать по этой структуре и отлавливать события.

Главный минус вызова poll() (хотя это, несомненно, был большой шаг вперед по сравнению с select()) — обход структуры с дескрипторами с точки зрения алгоритмики линеен, то есть осуществляется за O(n). Причем это касается не только отслеживания событий, но и реакции на них, да еще и надо передавать информацию туда-обратно из kernel space в user space.

А вот дальше в каждой операционной системе решили пойти своим путем. Нельзя сказать, что подходы конкретно различаются, но все-таки реализовать кросс-платформенную асинхронную работу с сокетами в своей программе стало чуточку сложнее. Под Windows появился API работы с так называемыми IO Completion Ports, в BSD-системах добавили механизм kqueue/kevent, а в Linux, начиная с ядра 2.5.44, стал работать системный вызов epoll. Отлов асинхронных событий на сокетах (как бы тавтологично это ни звучало) стал асинхронным сам по себе, то есть вместо обхода структур операционная система умеет подавать сигнал о событии в программу практически моментально после того, как это событие произошло. Кроме того, сокеты для мониторинга стало можно добавлять и убирать в любой момент времени. Это и есть те самые технологии, которые сегодня широко используются в большинстве сетевых фреймворков.

Зоопарк event loop’ов

Основная идея программирования с использованием вышеописанных штук состоит в том, что на уровне приложения реализуется так называемый event loop, то есть цикл, в котором непосредственно происходит отлов событий и дергаются callback’и. Под *nix-системами давненько уже существуют обертки, которые позволяют максимально упростить работу с сокетом и абстрагировать написанный код от низкоуровневой системной логики. Например, существует известная библиотека libevent, а также ее младшая сестра libev. Эти библиотеки собираются под разные системы и позволяют использовать самый совершенный из доступных механизмов мониторинга событий.

Я буду приводить в пример большей частью пакеты для сетевого программирования на языке Python, ибо их действительно там целый зоопарк на любой вкус, а еще они популярны и широко используются в различных проектах. Даже в самом языке довольно давно уже существуют встроенные модули asyncore и asynchat, которые, хоть и не умеют работать с epoll (только select/poll), вполне подходят для написания своих реализаций протоколов.

Одна из проблем сетевых библиотек заключается в том, что в каждой из них написана своя имплементация event loop’а, поэтому, даже несмотря на общий подход, перенос, скажем, плагина для Twisted (Reactor) на Tornado (IOLoop) или наоборот может оказаться вовсе не тривиальной задачей. Эту проблему призван решить новый встроенный модуль в Python 3.4, который называется asyncio и, вопреки расхожему мнению, не является сетевой библиотекой или веб-фреймворком в полном смысле слова, а является именно что встроенной в язык реализацией event loop’а. Эта штука как раз и призвана сплотить сторонние библиотеки вокруг одной общей стабильной технологии. Если хочется немного подробностей и независимых впечатлений об asyncio — милости прошу сюда.

Для Tornado уже существует реализация поддержки event loop’а из asyncio, и, более того, она не так давно вышла из состояния беты. Посмотреть можно здесь. Для Twisted релиз asyncio тоже не оказался неожиданностью, и его разработчики даже написали своеобразный шутливый некролог для проекта, в котором, напротив, уверяют, что это вовсе не конец, а очень даже начало новой эпохи развития.
Если говорить уж совсем откровенно, то понятие асинхронного ввода-вывода необязательно должно относиться именно к сетевому сокету. Системы семейства *nix следуют принципу, согласно которому взаимодействие фактически с любым устройством или сервисом происходит через file-like объект. Примерами таких объектов могут служить UNIX-сокеты или, скажем, ноды псевдофайловой системы /dev, через которые осуществляется обмен информацией с блочными устройствами. Соответственно, говоря об event loop’ах, мы можем подразумевать не только сетевое взаимодействие, но и просто любой асинхронный I/O. А чтобы было что потрогать руками — советую глянуть, например, вот на этот встроенный модуль из Python 3.4.

Запутанная история

В современном мире фреймворк Twisted выглядит таким своеобразным мамонтом, legacy-архаизмом, который впитал в себя все попытки предоставить удобный интерфейс для написания сетевых приложений. Тем не менее интерфейс получился действительно удобный, с реализацией отложенного выполнения кода и прочими плюшками, когда никакого Node.js еще не существовало и в помине.

Как я уже упомянул выше, реализация event loop’а в Twisted называется Reactor. Суть работы с ним состоит в том, что мы регистрируем callback’и, которые выполняются в глобальном цикле в виде реакции на какие-то события. Выглядеть это может, например, так:

Причем, даже если внутри callback возникнет исключение, то реактор все равно продолжит работать, после того как залогирует трейсбэк и запустит зарегистрированные обработчики ошибок.

Кстати, нельзя не уточнить, что Twisted по умолчанию однопоточный, то есть вся эта развесистая петрушка реализована на внутренней магии вокруг системных вызовов для асинхронного I/O. Но на случай крайней нужды в нем есть и своя реализация ThreadPool, которая добавляет возможность работы нескольких потоков.

Сюда идет Tornado

Если Twisted все-таки представляет собой больше сетевую библиотеку, чем веб-фреймворк, то c Tornado все ровно наоборот. Этот пакет был разработан теми же товарищами, которые делали FriendFeed, — а это, на минуточку, реально высоконагруженный веб-проект с миллионами посетителей в день. Отличие выражается еще и в том, что в нем есть небольшой встроенный шаблонизатор и поддержка всяких «интернетных» технологий вроде работы с куками и генератора HTTP-ответов в разных форматах.
Кстати, Tornado появился немного раньше, чем в Python появилась встроенная поддержка epoll (обертки вокруг сетевых системных вызовов находятся в модуле select), поэтому он поставляется с небольшой библиотекой для этого вызова, написанной в несколько строчек кода на C в виде импортируемого модуля. Эта обертка используется на старых версиях Python, но, говорят, в некоторых случаях специально руками собранный с ней пакет работает чуточку быстрее, чем на ванильной реализации. Да, еще одна городская легенда.

Twisted возник на горизонте раньше Tornado, однако тогда еще не начался этот бум на асинхронные веб-приложения, а когда он все-таки пришел, то Twisted оказался слегка не у дел в этой сфере, потому что изначально смотрел немного в другую сторону. Это выразилось в том, что веб-приложения на Twisted сейчас в основном пишут только приверженцы старой школы, а для Tornado появилось довольно большое число библиотек, которые добавляют, например, асинхронную работу с базами данных и key-value хранилищами, удобную интеграцию с фронтенд-технологиями наподобие SockJS и SocketIO и все такое прочее. В результате он сейчас является прямым конкурентом Node.js, только из мира Python.

В качестве примера асинхронного подхода рассмотрим такой код:

Про то, что такое корутины и как они работают, можно прочитать в моей статье в октябрьском номере. Этот код можно считать примером простейшего асинхронного приложения на Tornado — запускается сервер на 9999-м порту, который при заходе по URL «/test» запускает отложенную таску, в которой каждую секунду шлет следующее число из счетчика в сокет, при этом не забывая обрабатывать другие подключения.

Освещаем события

Асинхронные серверы — это круто, но как же насчет асинхронных клиентов? Такие тоже писать довольно легко. В Python это можно делать с использованием одной из двух довольно известных библиотек — gevent и eventlet. На их основе создаются отличные скоростные парсеры и системы мониторинга, которые по-настоящему быстро опрашивают тысячи серверов.

Нет, на самом деле серверы с их помощью тоже можно писать. Например, в известной облачной open source платформе OpenStack eventlet используется как база при построении REST-сервисов в некоторых подпроектах. Но в этих библиотеках также присутствует действительно хорошая инфраструктура для написания клиентов.

Gevent работает в основном с библиотекой libevent (или, в новых версиях, libev), а eventlet может при желании работать и просто с epoll. Основная задача этих модулей — создание удобной инфраструктуры для работы с корутинами и запуск тасков в «зеленом» режиме, то есть реализация кооперативной многозадачности за счет быстрого переключения контекста.

Например, в eventlet есть механизм манкипатчинга стандартной библиотеки Python, который позволяет при использовании, скажем, модуля threading, подменять потоки на корутины. То есть в общем случае написанная в многопоточном стиле программа становится асинхронной.

В качестве примера кода с переключением контекста приведу код из примеров стандартной библиотеки gevent:

А вот первый же пример простейшего асинхронного клиента на eventlet (его и другие примеры можно найти на официальном сайте):

Основной и главной проблемой этих модулей можно назвать то, что в силу их завязанности на код на C и хитрости реализации их до сих пор в нормальном виде не портировали ни на PyPy, ни на Python 3, есть только прототипы.

И что в итоге?

С одной стороны, асинхронный подход к программированию крайне полезен при решении целого ряда задач, особенно в сфере веб-разработки. С другой — он зачастую требует вывернуть мозг наизнанку, так как любая непродуманная строчка кода может привести к блокировке всего и вся. Но, несомненно, знание того, как работают подобные вещи, может быть очень полезным для современного разработчика, особенно в свете развития таких языков, как Go и Erlang, которые внутри себя скрещивают сразу несколько видов асинхронности и многопоточности в одном флаконе. Поэтому — категорически рекомендую пробовать, ошибаться, радоваться и вообще программировать. Удачи!

Цукерберг рекомендует:  Сайт - вопрос крутым программистам
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих