Приятный интерфейс по HTTP к ресурсам Интернет-радиостанции verdure_station. Можно в стиле Unix получать:
Ссылку на аудио-поток можно получить через промежуточный ресурс со списком доступных потоков в формате INI:
$ curl -s http://air.verdure.ru:8881/listen.pls
[playlist]
NumberOfEntries=1
File1=http://air.verdure.ru:8881/
Сам поток аудио выдаётся по протоколу SHOUTcast как audio/mpeg. Протокол не
полностью совместим с HTTP, а то бы было совсем здорово. Однако этот протокол
известен и поддерживается многими плейерами. Вот как сервер отдаёт аудио-поток:
$ curl -s http://air.verdure.ru:8881/ | head -n20
ICY 200 OK
icy-notice1:<BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>
icy-notice2:SHOUTcast Distributed Network Audio Server/FreeBSD v1.9.7<BR>
icy-name:verdure_station - www.verdure.ru
icy-genre:idm dark ambient deep
icy-url:http://www.verdure.ru
content-type:audio/mpeg
icy-pub:1
icy-br:128
[SHOUTcast data]
То есть ответ сразу начинается с тела без заголовков ответа HTTP. Зато сам ответ включает в себя HTTP-подобные заголовки протокола SHOUTcast.
Но всё это был более-менее известный SHOUTcast. Приятная вещь, которая меня порадовала, это листинг текущей программы в простом текстовом формате:
$ curl -s http://verdure.ru/list.txt
14:20 tisane - exclusive nightmare
14:56 phon.o - live@zona moscow 2004
15:47 deps - empty street
17:08 anton lanski - mokriy kofe
17:38 crab - katalog
...
12:53 acrotone - up the stairs
------------
beta lineup for verdure.ru, time is MSK GMT+4 (generated: 20100220 14:21:17)
То есть можно делать с ним практически любые вещи. Например, сделать отправку себе письма, если в ближайшее время будет микс понравившегося DJ.
В Unix приветствуется создание небольших взаимодействующих программ, каждая из которых решает одну задачу. В частности, именно за счёт процессов ОС решаются проблемы параллелизации и многозадачности. Поэтому важно, чтобы программа стартовала быстро и не выполняла того, о чём её не просит программист.
Недавно я заинтересовался языком Clojure, который исповедует монолитный подход к параллельности. Я решил провести небольшое сравнение скорости выполнения крошечных программ “Hello World” на разных языках. Вот результаты сравнения:
Я выпустил библиотеку iterpipes 0.3 для запуска конвейеров команд в Python с использованием синтаксиса shell. С её помощью может стать удобнее писать многие скрипты на Python, чем на bash.
Несколько дней назад я писал об автомонтировании накопителей USB в Linux. В том посте был приведён простой скрипт на shell для определения текущего пользователя:
#!/bin/bash
uids () {
users | tr " " "\n" | uniq
}
if [ `uids | wc -l` == 1 ]; then
uid=`uids`
else
uid="0"
fi
echo ACTIVE_UID="$uid"
Вот как этот скрипт будет выглядеть на Python с использованием iterpipes:
#!/usr/bin/env python
from iterpipes import cmd, run, join
users = set(run(cmd('users') | join).split())
uid = list(users)[0] if len(users) == 1 else 'root'
print 'ACTIVE_UID=%s' % uid
Многие скриптовые задачи удобнее решать на Python, чем на Bash. Но если в скрипте много конвейеров, то такой скрипт удобнее писать на Bash благодаря удобному и лаконичному конвейерному синтаксису.
Этому пора положить предел. Я хочу показать пример использования библиотеки конвейеров команд на Python, которую я пишу и чуть позже выложу.
В прошлом посте я разместил вспомогательный скрипт active_uid, написанный на
Bash и определяющий имя активного пользователя в системе. Он очень простой и
делает следующее. Если имена всех вошедших пользователей совпадают, то этот
пользователь и есть активный. Иначе это UID root:
#!/bin/bash
uids () {
users | tr " " "\n" | uniq
}
if [ `uids | wc -l` == 1 ]; then
uid=`uids`
else
uid="0"
fi
echo ACTIVE_UID="$uid"
Работает примерно так:
$ ./active_uid
ACTIVE_UID=vlan
А вот тот же самый скрипт, переписанный на Python с помощью будущей библиотеки. Замечу, что он намеренно оставлен таким же по структуре, хотя было бы намного проще разбить строки на Python без вызовов внешних процессов. Итак, скрипт:
#!/usr/bin/env python
from ... import runpipe, pipe, join, o
uids = join(runpipe(r'users | tr {} \n | uniq', ' '))
if o(int, join, pipe('wc -l'))(uids) == 1:
uid = uids
else:
uid = 'root'
print 'ACTIVE_UID=%s' % uid
А это более идиоматичный код на Python (хотя по-прежнему с композицией функций), где внешний процесс используется только для получения списка текущих пользователей:
#!/usr/bin/env python
from ... import runpipe, join, o
split = lambda s: s.split()
uids = o(list, set, split, join, runpipe)('users')
uid = uids[0] if len(uids) == 1 else 'root'
print 'ACTIVE_UID=%s' % uid
Here you can find markdown vim syntax file made by Ben Williams. Put it to the ~/vim/syntax/ folder.
To add syntax...
“This image was taken on September 15, 2006 and received on Earth September 20, 2006. The camera was pointing toward Saturn at approximately 2M...
Well, it looks like GCC 4.3.2 does not comply to C99 specification. It clearly states that:
6.8.6.4.1 ... A...