Показаны сообщения с ярлыком perl. Показать все сообщения
Показаны сообщения с ярлыком perl. Показать все сообщения

понедельник, 28 апреля 2008 г.

Google AJAX Language API

Великий Google порадовал разработчиков новым online сервисом «Google AJAX Language API». Функционал нового API — опреление языка текста и получение его перевода. На текущий момент поддерживается 13 языков, среди которых есть и русский. Переводы выполняются только на английский или только с английского языка, т.е. нельзя например напрямую перевести с русского на итальянский.

Чем это может быть полезно web-разработчику? Один из вариантов применения — генерация url-ов для динамического контента, по заголовку новости, теме в форуме или поста в блоге. А с кирилицей в урлах пока дела обстоят неважно. Например, урл новостей на ЛОРе никуда не годится в эпоху Web 2.0 :-)
http://www.linux.org.ru/view-message.jsp?msgid=2686861
Куда симпатичнее смотрелось бы:
http://www.linux.org.ru/news/ubuntu_8.04_released
или
http://www.linux.org.ru/news/2008/04/23/ubuntu_8.04_released

Сам Google позиционирует свой сервис для использования совместно с javascript. Однако, на практике, ничто не мешает применять любой другой язык программирования. Вот небольшой пример на perl, который позволяет получать онлайн перевод с русского на английский в консоли:

#!/usr/bin/perl -w
use strict;

use URI::Escape;
use LWP::UserAgent;
use JSON;

my $text       = $ARGV[0];
my $escaped    = uri_escape( $text );
my $user_agent = LWP::UserAgent->new;
$user_agent->env_proxy;
my $response   = $user_agent->get(
    "http://ajax.googleapis.com/ajax/services/language/translate" .
    "?v=1.0&q=$escaped&langpair=ru%7Cen"
)->content;
my $translated = jsonToObj($response)->{responseData}->{translatedText};

print $translated, "\n";


Пример использования:

$ ./ggl_trnslt.pl "Возьми моё сердце"
Take my heart

Если слово не найдено в словаре, то производится его транслитерация, что обычно лучше чем ничего:

./ggl_trnslt.pl паровоз
parovoz

Хотя и непонятно, почему Гугль не знает про паровозы... Остается надеяться что со временем качество перевода возрастет.

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

среда, 30 января 2008 г.

Веб-программирование на perl и шаблоны html страниц

Как я уже не раз замечал, обычно всякий веб-программист на perl проходит в своём развитии следующие стадии:

  1. Шаблоны станиц не используются. Характерно для начинающих, совсем зеленых ещё программистов. Вывод страниц формируется непосредственно внутри скрипта, примерно следующим образом:

    my $title = 'Hello world';
    print "Content-type: text/html\n\n";
    print "<html><head><title>$title</title></head>";

    Проект начинает расти и программист замечает, что становится неудобно вносить изменения в дизайн страницы. Редактирование исходного кода программы нелогично, ведь алгоритм работы остается неизменным! Работа с html тегами осложнена, они же встаиваются в синтаксис другого языка, появляется избыточный синтаксический мусор. Про разделение труда на программиста и верстальщика и вообще говорить нечего, здесь оно невозможно. Так программист приходит к следующей стадии.

  2. Самописная шаблонная система. Теперь вывод страниц формируется при помощи отдельной функции. Шаблон загружается из внешнего файла. С помощью регулярных выражений в нем организуется поиск и замена фрагментов кода, например специально помеченных комментариев:

    <table>
        <tr>
            <td><img src="logo.gif"></td>
            <td><!-- $TopMenu --></td>
        </tr>
        <tr>
            <td><!-- $LeftMenu --></td>
            <td><!-- $Content --></td>
        </tr>
    </table>

    Иногда реализуется функциональность вставки других файлов в шаблон (Include). По сравнению с начальным вариантом — это большой шаг вперед, программист освобождается от большинства описанных недостатков. Это уже не «ходьба пешком», но ещё и не «езда на лимузине». Обычно собственная шаблонная система работает неоптимально и не предоставляет многих возможностей разработчику. Многие программисты надолго, если не на всегда, застревают на данной стадии и необоснованно гордятся своими поделиями. Другие же обрашаются к:

  3. Одна из общепризнанных шаблонных систем. От самописной системы они отличаются возможностями:

    • Полное разделение логики программы и внешнего вида страницы. Весь html код находится в шаблоне, скрипт сам не выдает ни одного тега.
    • Условные вставки. Фрагмент шаблона появлется на странице при выполнении какого-либо условия.
    • Обработка циклов или массивов переменных. Например, к элементам массива может быть применена одинаковая разметка и сформирована html таблица.
    • Дополнительные возможности — кеширование шаблонов и/или сгенерированных страниц, подключение пользовательских плугинов/фильтров.
    • Годы поддержки и развития, хорошее быстродействие.

    В мире perl наиболее известными шаблонными системами являются:

Выбор конкретной системы — вопрос личных вкусов и предпочтений, я использую HTML::Template. Она мне нравится за простой язык шаблонов, напоминающий html теги, без попыток создать новый язык программирования. Но подробный рассказ о этой шаблонной системе — тема для отдельной статьи. В завершение хочу заметить что применять шаблоны можно не только для создания html страниц. На CPAN присутствуют модули для создания excel и pdf документов из xml шаблонов. Пример создания excel таблицы на perl из xml шаблона мною был уже описан.

понедельник, 5 ноября 2007 г.

Сравнение производительности perl кода

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

Задача. Как оптимальнее организовать перебор элементов хеша, например просуммировать значения всех ключей. В полном соответствии с принципом TIMTOWTDI существует несколько вариантов решения задачи:

Вариант №1. Использование цикла «foreach ( values ... )».

sub hash_values_sum_1(%) {
    my %hash = @_;
    my $sum = 0;
    $sum += $_ foreach values %hash;
    return $sum;
}

Вариант №2. Использование конструкции«map ... values ... ».

sub hash_values_sum_2(%) {
    my %hash = @_;
    my $sum = 0;
    map { $sum += $_ } values %hash;
    return $sum;
}

Вариант №3. Использование цикла «while ( ... each ... )».

sub hash_values_sum_3(%) {
    my %hash = @_;
    my $sum = 0;
    $sum += $_ while (undef, $_) = each %hash;
    return $sum;
}

Для проверки проверки напишем небольшой тестовый скрипт:

#!/usr/bin/perl -w
use strict;
use Benchmark qw/ :all /;

my %hash = map { rand, rand } ( 1 .. 1000 );

cmpthese( 5_000_000 , {
    var1 => 'my $sum = 0; $sum += $_ foreach values %hash',
    var2 => 'my $sum = 0; map { $sum += $_ } values %hash;',
    var3 => 'my $sum = 0; $sum += $_ while (undef, $_) = each %hash;',
} );

Проверяем производительность трех вариантов решения задачи. Для этого используем тестовый хеш, содержащий 1000 случайных ключей со случайными значениями. Для получения усредненных результатов, каждый из вариантов запускается по 5 миллионов раз. Результаты работы скрипта:

          Rate variant_1 variant_3 variant_2
var1  946970/s        --      -48%      -73%
var3 1838235/s       94%        --      -48%
var2 3546099/s      274%       93%        --

По таблице результатов видно, что:

  1. Вариант №3 работает почти в 2 раза быстрее, чем вариант №1.
  2. Вариант №2 работает почти в 2 раза быстрее, чем вариант №3.

В данном конкретном случае вариант №2 является однозначным победителем. Его использование более предпочтительно.

четверг, 2 августа 2007 г.

Правильная установка perl модулей в Slackware

Способ описанный в статье «Установка perl модулей» прекрасно работает. Но пользоваться им, значит идти в обход пакетной системы дистрибутива, что влечет следующие недостатки:

  1. Невозможность удалить perl модуль. CPAN.pm только обещает эти возможности в будущем.
  2. Некорректное обновление модулей. При установке новой версии модуля поверх старой, если должны быть удалены некоторые файлы из старой версии, этого сделано не будет. В лучшем случае это означает мусор в файловой системе, в худшем различные неприятные побочные эффекты.
  3. Невозможность получить список уже установленных модулей.
  4. Замусоривание файловой системы, невозможность определить какой файл к какой программе относится.

Предварительная сборка tgz пакетов Slackware позволяет устранить все вышеперечисленные недостатки. Кроме того, сборку пакетов можно производить не на рабочем сервере, а на отдельной машине, например виртуальной. Что в свою очередь даёт преимущества:

  1. Отсутствует необходимость в средствах сборки на рабочем сервере: make, компилятор, линковщик и т.д. Это экономит место на диске сервера и делает его более безопасным.
  2. Экономия времени, если рабочих серверов больше одного. Однажды собранные пакеты можно установить на много серверов. Установка готового пакета занимает секунды, сборка модуля длится гораздо дольше.

Переходим к практической части. Вначале необходимо сконфигурировать утилиту cpan, как написано в уже упомянутой статье «Установка perl модулей». Далее, для автоматизации процесса сборки Slackware пакетов из perl модулей нам поможет замечательная утилита cpan2tgz. С её помощью можно по имени модуля собрать Slackware пакет, а также пакеты всех отсутствующих зависимых модулей. На сайте автора утилиты cpan2tgz выбираем пакет под вашу версию Slackware, скачиваем и устанавливаем его:

root@slack12:~# wget http://software.jaos.org/slackpacks/12.0/cpan2tgz-0.6.2-norch-1.tgz
...
root@slack12:~# installpkg cpan2tgz-0.6.2-noarch-1.tgz
Installing package cpan2tgz-0.6.2-noarch-1... 
PACKAGE DESCRIPTION:
cpan2tgz: cpan2tgz - create Slackware packages from CPAN Perl modules
cpan2tgz: 
cpan2tgz: Packaged by cpan2tgz
cpan2tgz: 
cpan2tgz: cpan2tgz by Jason Woodward 
cpan2tgz: 
cpan2tgz: http://software.jaos.org/
cpan2tgz: 
Executing install script for cpan2tgz-0.6.2-noarch-1...

Чтобы получить пакеты, например, runtime части web фремворка Catalyst можем воспользоватся командой:

root@slack12:~# cpan2tgz Catalyst

Начнется сборка пакетов, при этом большую часть времени работает утилита cpan, скачивая, распаковывая и устанавливая perl модули. После установки модуля cpan2tgz запаковывает его в tgz пакет с соблюдением стандартов. По умолчанию готовые пакеты помещаются в директорию /usr/src . В данном случае список состоит из:

perl-catalyst-runtime-5.7007-noarch-1.tgz
perl-cgi-simple-1.1-noarch-1.tgz
perl-class-accessor-0.31-noarch-1.tgz
perl-class-data-inheritable-0.06-noarch-1.tgz
perl-class-inspector-1.16-noarch-1.tgz
perl-compress-raw-zlib-2.005-i486-1.tgz
perl-compress-zlib-2.005-noarch-1.tgz
perl-data-dump-1.08-noarch-1.tgz
perl-file-modified-0.07-noarch-1.tgz
perl-html-parser-3.56-i486-1.tgz
perl-html-tagset-3.10-noarch-1.tgz
perl-http-body-0.9-noarch-1.tgz
perl-http-request-ascgi-0.5-noarch-1.tgz
perl-io-compress-base-2.005-noarch-1.tgz
perl-io-compress-zlib-2.005-noarch-1.tgz
perl-libwww-perl-5.806-noarch-1.tgz
perl-module-pluggable-3.6-noarch-1.tgz
perl-path-class-0.16-noarch-1.tgz
perl-sub-uplevel-0.14-noarch-1.tgz
perl-test-exception-0.25-noarch-1.tgz
perl-text-simpletable-0.03-noarch-1.tgz
perl-tree-simple-1.17-noarch-1.tgz
perl-tree-simple-visitorfactory-0.10-noarch-1.tgz
perl-version-0.7203-i486-1.tgz
perl-yaml-0.65-noarch-1.tgz

Теперь можно скопировать эти пакеты на рабочий сервер и установить c помощью команды:

root@slack12:~# installpkg *.tgz

Всё.

пятница, 6 июля 2007 г.

Генерация Excel документов на perl

Описание задачи. Имеется программная телефонная станция на базе asterisk. Журнал звонков этой телефонной станции ведется в базе данных mysql. Названия полей таблицы соответствуют названиям полей CDR (Call Detail Record). Возникла необходимость в доступе к этому журналу для менеджеров. Менеджеры, братья наши меньшие, абсолютно не очарованы таблицами баз данных, SQL для них чужд. Зато документы в формате Excel милы их сердцам. Поэтому напишем perl скрипт для генерации Excel отчета из базы данных. Для создания excel файлов воспользуемся perl модулем Excel::Template, позволяющем, как видно из названия, создавать .xls файлы на основе xml шаблона. Вы ведь не хотите менять программу каждый раз, когда нужно будет увеличить размер шрифта или поменять местами колонки в отчете? Сначала приведем содержимое файла шаблона report.xml:
<workbook>
 <worksheet name="report">
   <format align="center" valign="vcenter" bold="bold" border="2">
     <row>
       <cell width="15">Откуда</cell>
       <cell width="15">Куда</cell>
       <cell width="15">Начало</cell>
       <cell width="15">Длительность</cell>
     </row>
   </format>

   <format border="1">
     <loop name="report_data">
       <row>
         <cell><var name="src" /></cell>
         <cell><var name="dst" /></cell>
         <cell><var name="start" /></cell>
         <cell><var name="billsec" /></cell>
       </row>
     </loop>
   </format>
 </worksheet>
</workbook>
В данном шаблоне описывается excel документ, содержащий один лист с данными. На этом листе первая строка содержит заголовки 4-х колонок отчета: «Откуда» — номер вызывающего абонента, «Куда» — номер вызываемого абонента, «Начало» — время начала звонка, «Длительность» — длительность звонка. Остальные строки заполняются данными отчета по количеству записей в нём. Подробное описание всех тегов шаблона присутствует в документации perl модуля Excel::Template. Теперь сам скрипт report.pl:
#!/usr/bin/perl -w -t
use strict;

use DateTime;
use DBI;
use Excel::Template;

# подключение к базе данных
my $dsn    = 'dbi:mysql:database=...;host=...';
my $dbuser = '...';
my $dbpass = '...';
my $dbh    = DBI->connect( $dsn, $dbuser, $dbpass, { RaiseError => 1 } );

# задаем период формирования отчета
my $period_begin = DateTime->new( year => 2007, month => 6, day => 1 );
my $period_end   = DateTime->new( year => 2007, month => 7, day => 1 );

# подготовка и исполнение sql запроса на выборку данных
my $sth = $dbh->prepare( q/
    SELECT `src`, `dst`, `start`, `answer`, `end`, `duration`
    FROM   `cdr`
    WHERE  `start` BETWEEN ? AND ?
/ );
$sth->execute( $period_begin, $period_end );

# извлечение данных из базы и подготовка их для шаблона
my @report_data;
while ( my $report_row = $sth->fetchrow_hashref ) {
    push @report_data, $report_row;
}

# формирование excel отчета по шаблону и данным
my $template_file = 'report.xml';
my $template = Excel::Template->new( filename => $template_file );
$template->param( report_data => \@report_data );
print $template->output;

Скрипт report.pl выдает excel отчет на стандартный поток вывода, поэтому вызывать его нужно так: « ./report.pl > report.xls ». Как видите — ничего сложного. Подобным же образом можно генерировать excel документы и для web.

P.S. Данный скрипт работоспособный, хотя и был немного упрощен, чтобы донести основную идею использования шаблонов. На самом деле условия отбора записей сложнее, период формирования отчета задается в аргументах скрипта report.pl; даты преобразуются во внутренний формат excel, а не вставлются текстовой строкой; решены вопросы c кодировками. Но опытному perl программисту не составит труда адаптировать этот скрипт под свои нужды.

среда, 4 июля 2007 г.

Установка perl модулей

CPAN - это средоточие интеллектуальной мощи десятков известных и (и сотен не очень известных) perl-хакеров. Это сетевой архив тысяч perl модулей, охватывающий абсолютно все мыслимые области применения программирования. Определенно, perl сегодня не занимал бы того место, которое он занимает сейчас, если бы не было CPAN, отметившего в 2005 году своё десятилетие. Правилом любого perl программиста должно быть: сначала ищи на CPAN и только потом, в случае отсутствия там, уже пиши сам. Ведь работодатель вас ценит и платит за то, что вы умеете быстро собирать работающие машины (программы) из готовых запчастей (perl модули из CPAN), а не тратите недели рабочего времени на изобретение заново колес и шестеренок (библиотеки классов и функций). Perl модули распространяются в виде архивов исходного кода с расширением .tar.gz. В одном архиве исходного кода может быть несколько perl модулей. Основной веб-интерфейс для работы с CPAN — http://search.cpan.org. На этом сайте можно найти интересующий perl модуль по структурированному каталогу или по имени. Для каждого модуля можно прочитать встроенную документацию и исходный код. Как правило, все perl модули очень хорошо документированы. Естественно, можно скачать архив исходного кода. В каждом архиве исходного кода прилагается инструкция по установке, обычно она включает распаковку архива и выполнение команд:
perl Makefile.PL
make
make test
make install
Такой метод установки прекрасно работает, но им неудобно пользоваться. Почему? Из-за зависимостей модулей. Например, для установки часто используемой библиотеки модулей LWP (libwebperl — библиотека для работы с web из perl) требуются уже установленные perl модули: URI, Compress::Zlib, HTML::Parser. В свою очередь, для установки модуля Compress::Zlib требуются уже установленные модули: IO::Uncompress::Gunzip, IO::Compress::Gzip, Compress::Raw::Zlib, IO::Uncompress::Base, IO::Compress::Gzip::Constants, IO::Compress::Base и IO::Compress::Base::Common. И так далее... дерево зависимостей может быть очень большим. Скачивать и устанавливать все модули в ручную — просто потеря времени. Для автоматизации процесса разрешения зависимостей существует специальный perl модуль CPAN. В его состав входит утилита cpan, предоставляющая консоль доступа к архиву. Ею мы и будем пользоваться. При первом запуске утилиты будет задано несколько вопросов по параметрам конфигурации. Ответы по умолчанию выбраны достаточно разумно, поэтому я не вижу смысла отказываться от автоматического конфигурирования:
root@slack11:~# cpan
/usr/lib/perl5/5.8.8/CPAN/Config.pm initialized.
...
Are you ready for manual configuration? [yes] no
...
cpan shell -- CPAN exploration and modules installation (v1.7602)
cpan>
Если для доступа в интернет используется http proxy сервер, то необходимо задать параметры ftp_proxy и http_proxy. Если proxy сервер требует авторизацию, то url задается по схеме "http://login:password@adrr:port/":
cpan> o conf ftp_proxy "http://adrr:port/"
    ftp_proxy          http://adrr:port/
cpan> o conf http_proxy "http://adrr:port/"
    http_proxy         http://adrr:port/
cpan> o conf commit
Чтобы проверить связь cpan с внешним миром, можно загрузить информацию о текущем состоянии базы данных модулей:
cpan> reload index
Теперь модуль CPAN сконфигурирован и готов к работе. Например, можно установить уже упоминавшуюся библиотеку LWP со всеми зависимостями с помощью команды:
cpan> install LWP
Остается только смотреть на мелькающие надписи, чувствуя себя в матрице. Однако полностью расслабится не удастся, изредка придется отвечать на возникающие на экране на вопросы. Вот собственно и всё, теперь установить любой perl модуль — дело нескольких минут. В завершение хочется отметить, что алгоритм разрешения зависимостей модулей постоянно совершенствуется, changelog впечатляет. Поэтому можно порекомендовать обновить саму утилиту cpan и установить дополнительные модули, облегчающие её работу. Утилита cpan может обновить сама себя, для этого следует выполнить команду:
cpan> install Bundle::CPAN
После обновления утилиты cpan, её надо перезапустить, чтобы изменения вступили в силу. Скорее всего придется заново пройти этап конфигурирования, в автоматическом режиме, конечно :-). Вы сразу заметите, что в консоле cpan появилась возможность пролистать историю ранее введенных команд.