Xpoint
   [напомнить пароль]

Вызов функций из других скриптов

Метки: [без меток]
[удл]
2007-04-15 04:19:27 [обр] speed[досье]
сообщение промодерировано

Помогите реализовать следующую вещь или понять как реализовать.

Есть скрипт - main.pl
Есть множество вспомогательных скриптов: script1.pl, script2.pl, script3.pl ...
В каждом скрипте есть некая функция (или функции - пока еще не понял надо их одинаково называть или по разному), но допустим функция во всех скриптах называтся одинаково.

В скрипте main.pl имеется запрос в базу, в результате которого мы получаем 2 параметра $id - id записи и $script - имя скрипта. Получаемый $id мы должны использовать в файле $script.pl при вызове этой функции.

В голову приходит такая вот реализация:

my $sth = $dbh->prepare($sql); $sth->execute();   
while(my($id, $script) = $sth->fetchrow_array())
{
do "$script";
&add($id);
}
$sth->finish();

В принципе работает, но если в цикле у нас 100 записей, а скрипт весит 20-30-50 кб, то все это дело не очень быстро работает.

Допустим, что можно сделать 2 запроса - один сгруппирует записи по имени скрипта и прорекваирит эти скрипты, второй запрос будет вызывать функции и передавать в них $id. Однако тогда надо функции в скриптах называть по разному. Но как их тогда вызывать не зная их названий?
Была идея называть функцию в виде add_имя_скрипта, однако такая версия не подошла, т.к. планируется что можно просто сделать копию скрипта script1.pl ничего не меняя внутри самого скрипта и назвать его script4.pl, который в дальнейшем использовать (не буду объяснять зачем 2 одинаковых скрипта).

Плюс еще такой ньюанс. В каждом скрипте примерно одинаковый набор функций с одинаковыми названиями. Желательно чтобы после выполнения функции add скрипт со всеми его функциями выгружался из памяти. Или при рекваире загружался только с этой функцией.

Понимаю, что написал немного заморочено, но может кто сможет что посоветовать?

спустя 6 часов [обр] AB...(10/233)[досье]
Проще всего написать модуль. В скрипте создаете объект этого модуля и потом просто работаете с объектом.
Честно говоря никогда не использовал в таком варианте другие скрипты как в вашем условии, но можете попробовать require и проверить на сколько он будет потреблять ресурсов.
спустя 3 часа 45 минут [обр] Алексей Севрюков(198/1280)[досье]
Плюс еще такой ньюанс. В каждом скрипте примерно одинаковый набор функций с одинаковыми названиями.

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

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

В принципе работает, но если в цикле у нас 100 записей, а скрипт весит 20-30-50 кб, то все это дело не очень быстро работает.

Ну а что вы хотите, ведь получаеися что у Вас компилится от 2 до 5 мб скриптов, и при этом читается 100 файлов, конечно это будет медленно.

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

спустя 1 день 1 час [обр] Закиров Руслан(69/341)[досье]

Каждый скрипт первращаем в модуль:

package MyApp::Spript1;

здесь ваши функции

1;

Чтобы не писать страшные конструкции потом, в каждой функции добавляем в самом начале my $self = shift;. Это потом вам поможет перейти к ОО программированию, ибо его вы и пытаетесь эмулировать.

В основном скрипте добавляем вначале:

use lib qw(/path/to/dir/with/lib);

В этой папке пакеты располагаем следующим образом:

/path/to/dir/with/lib/MyApp/Script1.pm
/path/to/dir/with/lib/MyApp/Script2.pm
...

Теперь в main.pl можно написать use MyApp::Script1;, require MyApp::Script1; или eval "require MyApp::$name_of_script" or die "Couldn't load $name_of_script: $@";.

Каждый ваш набор будет загружен в определенное пространство имен и только один раз.

Теперь вы можете вызывать функции используя: MyApp::Script1->function(...); или сохранив имя пакета в переменной my $class = "MyApp::Script1"; $class->function(...);

Используя ваш пример, получаем:

use lib qw(/path/to/libs);
...
my $sth = $dbh->prepare($sql); $sth->execute();   
while(my($id, $script) = $sth->fetchrow_array())
{
  my $module = "MyApp::$script";
  eval "require $module" or die "Couldn't load $module: $@";
  $module->add($id);
}
$sth->finish();

Это только один вариант решения, а их великое множество. Далее читаем документацию по модулям и ОО в perl.

Powered by POEM™ Engine Copyright © 2002-2005