source для virtualenv под windows

Иногда бывает нужно сделать свой, небольшой локальный Python-мирок. Например, если мы пишем на djan­go и не хотим ставить пакеты глобально.

Официальная документация по djan­go советует vir­tualenv. Действия такие:

$ virtualenv env
$ source env/bin/activate

А потом мы работаем в этой папке, как если бы именно она была у нас системной.

Но если вы вынуждены работать под Win­dows (например, такова политика компании), то это невозможно — в языке консоли Win­dows нет команды source или её аналога. Да и в Pow­er­shell она сводится к запуску скрипта в определённом контексте.

Самый лучший выход — поставить cyg­win. Он ставится быстро, осваивается за несколько минут (логические диски — это папки вида /cygdrive/c/, остальное как привыкли) и позволяет писать строго по инструкции.

Правда, многих пакетов, который нам понадобятся, в нём по умолчанию нет. Поэтому надо их дополнительно поставить.

Для начала — при установке укажите, что хотите поставить Lynx. Если вы забыли — просто запустите установку ещё раз и укажите нужный пакет, он сам докачает и положет в нужную папку.

Потом ставим скрипт apt-cyg, который эмулирует apt-get.

lynx -source rawgit.com/transcode-open/apt-cyg/master/apt-cyg > apt-cyg
install apt-cyg /bin

Теперь начинаем ставить командами в духе apt-get install wget (пока wget-а нет, он будет качать через lynx)

И дальше по инструкции для Python

Ставим пакеты, настраиваем и приступаем к работе. Или просто берём готовую сборку.

В процессе установки пакетов есть риск подорваться. Если попытаться поставить их через ez_setup.py, то внезапно узнаешь, что urllib2.HTTPError: HTTP Error 403: SSL is required.

Это связано с тем, что Pip поменял правила доступа к репозиторию. И давно обзавёлся своим инсталлятором:

apt-cyg curl # если ещё не ставил
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py

Далее настраиваем, как положено, и наслаждаемся vir­tualenv.

  • Создать: mkvirtualenv my-first-env
  • Запустить: workon my-first-env
  • Завершить: deactivate
  • Удалить: rmvirtualenv my-first-env

Как C и Perl захватили планету

Почему C и Perl стали стандартами в своих областях и до сих пор на коне?

Дело, конечно, не только в синтаксисе и парадигме. И даже не в простоте. C, конечно, прост, это по-человечески записанный кроссплатформенный ассемблер. Но Perl совсем не прост, это многослойная обёртка вокруг парсера регулярных выражений.

Весь секрет — в нечестных преимуществах.

Компиляторы C были под все платформы и бесплатно. А какой-нибудь Pas­cal был разный и платный.

Perl изначально создавался для работы с текстом, парсинга, преобразования и т.п. А протокол HTTP целиком текстовый. Вот и писались ранние скрипты на Perl-е.

Потом появился PHP, где были те же регулярки, но c привычными классами и он был тупо проще в освоении. И о Perl для веба стало неудобно говорить. Такое же логичное развитие Perl, как C++ — для C. И как Java — для C++.

А потом появился Python, паттерн MVC дал Ruby on Rails и всё стало как сейчас. Наконец, желание писать даже на сервере знакомым синтаксисом породило Node­JS.

Провал всех без исключения “функциональных решений” немножечко предсказуем — потому что нет области, где они были бы нужны и на голову превзошли конкурентов. Go выстрелил, потому что добавил в чистый C всё, чего там не хватало. Scala — потому что это лаконичная Java. Swift — потому что Mac.

 

SHA256 в Python

SHA256 в Python бывает и стандартный (из hash­lib), и сторонний (из PyCryp­to). Интересно, что при неосторожном использовании они дают разные результаты.

Во-первых, SHA256.new() из PyCryp­to сразу после создания имеет digest. Это SHA от пустой строки — широко известное 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.

Во-вторых, каждый update накладывается в нём на предыдущий, поэтому если digest используется на следующей итерации, то SHA256.new() надо пересоздавать. То есть аналог

h = hashlib.sha256(data + h).digest()

Это

hsh_exec = SHA256.new()
hsh_exec.update(data + hsh)
h = hsh_exec.digest()

Д. Босуэлл, Т. Фаучер — Читаемый код, или программирование как искусство

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

Например, более точные варианты названий для типичных функций:

send — deliv­er; dis­patch; announce; dis­trib­ute; route
find — search; extract; locate;recover
start — launch; cre­ate; begin; open
make — cre­ate; set­up; build; gen­er­ate; com­pose; new

Именованные интераторы для циклов (ui лучше, чем просто i).

Дополнительные постфиксы — size_mb, html_utf луче, чем size и html.

first/last — это включающие, а begin/end — исключающие границы.

Пометы в комментах:

TODO - задумано, но не сделано.
FIXME - известно, что есть проблема
HACK - неэлегантное решение проблемы
XXX - серьёзная проблема

Уже второе недоумение насчёт цикла do-while (которые непонятно, зачем нужен).

Разоблачён миф о том, что из функции должен быть только один выход. Он тянется из чистого C, где нередко забывали вычистить память перед выходом. Но c тех пор появились исключения, деструкторы и очистка мусора. А в C простительно писать goto cleanup;

Вообще, если удаётся уменьшить количество отступов, — это хорошо.

Запутывают код: многопоточность, обработчики сигналов/прерываний, исключения, указатели на функции и анонимные функции, виртуальные методы.

В JavaScript и Python переменная, объявленная внутри цикла, будет видна и снаружи. Вообще, область видимости переменных надо сужать. А самые лучшие переменные — константы, поэтому лучше всего менять их один раз.

Переменные объявлять где используются, а не в начале блока. Объявлять всё в начале блока — дурная традиция из Pas­cal и раннего C (хотя в C99 уже разрешили объявлять где угодно).

Также есть приятные куски кода:

Макрос для C++, чтобы убрать warn­ing для неопределённого конструктора копирования или оператора присваивания.

#define DISALLOW_COPY_AND_ASSIGN(ClassName) 
  ClassName(const ClassName&); 
  void operator=(const ClassName&);

И потом писать:

class ClassName {
  private:
     DISALLOW_COPY_AND_ASSIGN(ClassName);
     ...
  public:
     ...
};

Python: размер по числу байт

def get_bytes_size_units(num):
  """ Get file size with proper units of measurement.
  """
  range_titles = ["b", "kB", "Mb", "Gb", "Tb", "PB", "EB", "ZP", "YB"]
  range_titles_len = len(range_titles)
  i = 1
  prev_value = 0
  new_value = num
  is_iteration = True
  while is_iteration:
    prev_value = new_value
    new_value = num >> ((i << 1) * 5)
    i += 1
    is_iteration = new_value < 0 and i < range_titles_len
  i -= 2
  return "%.2f%s" % (float(num) / float(1 << ((i << 1) * 5)), range_titles[i])

WordCount в Sublime

Sub­lime чудесен. Можно сказать, что проблема отсутствия под lin­ux-ом Notepad++ успешно решена.

Правда был вопрос – насколько можно его использовать для написания всяких текстов. А чтобы в программе писали тексты, она должна уметь подсчитывать символы.

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

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

Обновлённый код успешно merged и залит в основную ветку.

А удивил меня сам алгоритм подсчёта. Их там целых два, причём первый закомментирован:

#=====1
# wrdRx = Pref.wrdRx
# """counts by counting all the start-of-word characters"""
# # regex to find word characters
# matchingWrd = False
# words = 0
# for ch in content:
# # # test if this char is a word char
# isWrd = wrdRx(ch)
# if isWrd and not matchingWrd:
# words = words + 1
# matchingWrd = True
# if not isWrd:
# matchingWrd = False
#=====2
wrdRx = Pref.wrdRx
words = len([x for x in content.replace('n', ' ').split(' ') if False == x.isdigit() and wrdRx(x)])

На первый вгляд, алгоритм 1 должен работать лучше и экономней. Фактически, перед нами нечто наподобие state machine, и его сложность не больше o(n). В то время как второй алгоритм создаёт кучу новых элементов только для того, чтобы их пересчитать.

На самом деле алгоритм 2 отрабатывает намного быстрее, чем 1. Например, чтобы подсчитать количество слов в “Петербургских трущобах” Крестовского, 2-ому нужно порядка 1 сек., а первому – 2.

Вот вам и оптимизация.