Выбор версии языка программирования, фреймворка - сложный вопрос, который всегда бурно обсуждался и будет обсуждаться. В enterprise мире часто, но не всегда, используют старые и проверенные инструменты. В то время как Python 2.7 все еще нет из коробки в RedHat/CentOS/др дистрибутивах, в некоторых уже используется Python 3.3, пусть и не в качестве системного. В мире opensource - наоборот, часто используют только самое-самое новое. Но это правило не относится к разным фреймворкам. Представьте, что завтра, например, Django будет поддерживать только Python 3.4, который еще не зарелизился. Никто им пользоваться не будет. Вот и приходится поддерживать несколько версия языка программирования. Похожая ситуация с paramiko, nose и другими популярными проектами/инструментами/библиотеками.

Сегодня, пытаясь настроить Travis CI для небольшокго плагина для nose (https://github.com/mahmoudimus/nose-timer), столкнулся с проблемой немного удивился в отличии списка поддерживаемых версия питона nose, а в следствии и nose-timer, и Travis CI. Travis работает только с несколькими самыми используемыми версиями - 2.6, 2.7, 3.2 и 3.3 (http://about.travis-ci.org/docs/user/languages/python/). Для меня это показатель: раз такой популярный инструмент поддерживает эти версии, то следует задуматься какие версии python'а нужно поддерживать в своих библиотеках.

 

P.S. А тем временем стал доступен Python 3.4.0 beta 2.


Если коротко, то типы в Python делятся либо на встроенные и пользовательские, либо на mutable и immutable (сразу так и не подобрал подходящего перевода на русский язык). Ну а если немного подробнее, то как-то так:

Рассмотрим простой пример кода (здесь и далее примеры кода будут писаться и выполняться в ipython’е):

In [1]: a = 1000
In [2]: a
Out[2]: 1000
In [3]: type(a)
Out[3]: int

Здесь мы объявляем переменую создаем объект (object) a, со значением(value) 1000 типа(type) int. Объекты в python - это абстрация над данными. Поэтому любой объект содержит в себе идентификатор(identity), тип и значение. Идентификатор - это адрес объекта в памяти, который никогда не меняется. Но мы можем присвоить объекту новое значение, написав, следующий код:

In [4]: a = 'hello'
In [5]: a
Out[5]: 'hello'
In [6]: type(a)
Out[6]: str

Теперь мы присвоили объекту a новое значение типа string. За кулисами этого всего, интерпритатор сделал, примерно, такое: создал новый объект ‘hello’, и поменялл ссылку переменной a на новый объект в памяти. При этом старое значение 1000 все еще хранится в памяти и будет удалено сборщиком мусора, т.к. на него нет ни одной ссылки. Тоже самое происходит и присвоении переменной нового значений такого же типа:

In [7]: b = 1000
In [8]: id(b)
Out[8]: 40235856
In [9]: b = 1001
In [10]: id(b)
Out[10]: 39189680

Интересный эффект будет при использовании целых чисел в диапазоне от -5, до 256 - их id всегда будет одинаковый, т.к. для улучшения быстродействия интерпритатор при старте создает объекты с этими значениями.

Стандартные типы в CPython делятся на два типа: mutable и immutable. Mutable — это обекты, значения которых могут быть изменены(например, list), а immutable — это обекты, значения которых не может меняться (например, string). Но это не значит, что если у нас есть переменная immutable типа, то ее нельзя изменить. Например, с типом string все привыкли работать так:

In [11]: text = 'Hello'
In [12]: text
Out[12]: 'Hello'
In [13]: text = 'Hello, World'
In [14]: text
Out[14]: 'Hello, World'

Как мы видим, начение переменной text поменялось. На самом деле, при присвоении переменной text нового значения, в памяти создается новый объект, и переменная text начинает на него ссылаться. В этом легко убедится при помощи функции id - получить идентификатор до и после изменения переменной.

Mutable типы ведут себя так:
In [15]: l = [1, 2, 3]
In [16]: l
Out[16]: [1, 2, 3]
In [17]: id(l)
Out[17]: 139901299808088
In [18]: l.append(4)
In [19]: l
Out[19]: [1, 2, 3, 4]
In [20]: id(l)
Out[20]: 139901299808088

Основываясь на этом свойстве(и не только), ключами в словаре (dict) могут быть только immutable обекты:

In [21]: d = {'one': 1}
In [22]: type(d)
Out[22]: dict
In [23]: d[1]=1
In [24]: d
Out[24]: {1: 1, 'one': 1}
In [25]: d[l] = 'list'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-25-4f49b18d7af7> in <module>() ----> 1 d[l] = 'list'
TypeError: unhashable type: 'list'

Immutable типы в Python — это числа(numbers), строки (strings) и кортежи (tuples).

Для облегчения привжу список некоторых всторенных типов (built-in types):

 

  • Numbers (числа) — int, long, float, complex(3+4j), Decimal, Fraction
  • Sequence Types (последовательности) — str, unicode, list, tuple, bytearray, buffer, xrange
  • Sets — set, frozenset
  • Maps (хеш-таблицы) — dict
  • Files, context managers и другие.

 

Ссылки по теме:

 

 

 


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

По сути, всем все-равно в какой IDE пишете код, если он работает так, как надо и написан вовремя. Унификация средст разработки внутри компании/команды лишь облегчает жизть менеджерам, ИТ, новым членам команды и упрощает коммуникацию между разработчиками. Ведь на много легче один раз написать инструкцию по установки всего нужного для запуска проекта ПО, например, для Ubuntu 13.10 x64 и запуск проекта в PyCharm, чем каждый раз сталкиваться с проблемой как запустить X в окружении Y.

Но каждый разработчик в праве решать сам чем он будет пользоваться. Вот только к выбору инструментов нужно подходить “с умом”. Главное - хорошо знать инструменты, которыми вы пользуетесь. Иначе будет ситуация, когда используется Photoshop только для изменения размера картинки. Досконально знать OS, IDE, текстовый редактор, которым пользуетесь каждый день не только приятно, но и полезно. Это может экономить массу времени. Всем известно, что использования горячих клавиш, в некоторых условиях, в разы быстрее, чем совершать нужные действия мышкой. Аналогичная ситуация с разнообразными инструментами автоматизации. Если мне нужно выполнить действиее более 2-3х раз - я пишу небольшой скрипт на bash или python. Иногда скрипты получаются не очень и маленькими, иногда в помощь приходят fabric/chef/puppet. Готовые настройки для используемых редактором и систем (профайлы bash, zsh) - упрощают жизь и экономят время, которое можно потратить на более полезные и интересные вещи.

Все вышесказанное всем известно и описано в множестве книг и постов. Захотелось повторить, т.к. я в очередной раз наступил на эти грабли: потратил почти час на написание простого скрипта на bash’е, аналог которого на python мне удалось написать за 10 минут. Да, я узнал кое-что новое о bash, но это не мой основной язык программирования, и скрипт писался исключительно для себя (и не важно, что любой может скачать его с github и пользоваться), но я потратил массу времени из-за того, что выбрал не тот инструмент. Нельзя путать процесс обучения и процесс разаботки. Между ними очень тонкая грань, которую легко перейти и потерять время напрасно.


Всегда недолюбливал Apache из-за формата его конфига. Конфиг Nginx’а мне вседа было порще читать и писать. Да и статику им раздавать хорошо и быстро, поэтому от Apache я, по возможности, отказываюсь. Но частая проблема с nginx в том, что приходится собирать необходимые модули из исходников самому, со всемы вытикаюющими плюсами и минусами. И, как полагается любому популярному и быстро развивающемуся проекту, документация по сборке этих самих модулей не всегда полная и актуальная.

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

Оффициальная документация расположена тут и тут. При этом сложилось впечатление, что на github’е она более актуальная и полная. По ним можно собрать все, при условии, что у вас уже стоят нужные пакеты. Мне понадобились:

$ sudo apt-get install autoconf automake libtool libcurl4-openssl-dev

Тажке, не забыть выполнить “./autogen.sh” перед “./configure”. Почему-то, в секции “Installation for NGINX” документации написаны только общие сведения. Мне, например, не хотелось и не нужно было собирать mod_security для apache, устанавливать пакет apache2-dev и т.д. Поэтому выполнил configure со следующими параметами:

$ ./configure --prefix=/usr --disable-apache2-module --enable-standalone-module

Далее сборка, установка и настройка у меня прошла без проблем.