Как я могу использовать lib в соответствующем каталоге в зависимости от места установки? - PullRequest
6 голосов
/ 11 ноября 2009

У меня есть объектно-ориентированное веб-приложение, которое установлено в нескольких местах на моем сервере. Один раз для «живого», один раз для «бета» и т. Д. Будучи объектно-ориентированным, он состоит из множества модулей Perl. В главном модуле я должен «использовать lib» соответствующий каталог для всех пользовательских модулей perl для этого экземпляра приложения.

Это не страшно, у меня есть блок BEGIN, который проверяет местоположение основной программы и устанавливает каталог библиотеки соответствующим образом. Однако у меня также есть много утилит, программ командной строки, которые должны делать то же самое. Я не хочу вырезать и вставить этот код везде.

Как лучше всего передать этот фрагмент кода различным программам, которым он нужен?

Я не могу "использовать" его, потому что путь к библиотеке не установлен. Возможно, "do" или "require" будет правильным ответом, но оба они будут искать @INC, что неуместно.

Может быть, что-то вроде eval `cat GetLib.pl`; было бы уместно, но кажется немного неуклюжим и хрупким.

Вот блок BEGIN, который я сейчас использую:

BEGIN {
  use FindBin qw ($Bin);
  require lib;

  if ($Bin =~ /^\/home\/w\/myapp_live/) {
    lib->import('/home/w/myapp_live/lib');
    print STDERR "live site\n";
  }

  if ($Bin =~ /^\/home\/w\/myapp_beta/) {
    lib->import('/home/w/myapp_beta/lib');
    print STDERR "beta site\n";
  }

  if ($Bin =~ /^\/home\/w\/myapp_test/) {
    lib->import('/home/w/myapp_test/lib');
    print STDERR "testing site\n";
  }

}

Спасибо!

Ответы [ 5 ]

7 голосов
/ 11 ноября 2009

FindBin :: libs отлично подходит для этого. Я использовал его некоторое время в большой системе без проблем.

Вызов по умолчанию выглядит так, как будто он будет работать для вас, просто:

use FindBin::libs;

Будет выполнен поиск всех ./lib каталогов во всех родительских каталогах каталога текущего файла и use lib их. Так, например, если ваш скрипт находится в /home/w/myapp_live/scripts/defurblise_widgets.pluse() es FindBin :: libs), он будет искать:

/home/w/myapp_live/scripts/lib
/home/w/myapp_live/lib
/home/w/lib
/home/lib
/lib       # (presumably!)

Все, что он найдет, будет добавлено к вам @INC с use lib.

Но, если это не совсем то, что вам нужно, это очень гибкий модуль. Я был бы удивлен, если бы вы не могли найти способ заставить его делать то, что вы хотите.

5 голосов
/ 11 ноября 2009

Если вы запускаете программу из командной строки, не устанавливайте библиотеку программно: просто передайте ее в качестве аргумента, например: perl -I/location/of/my/lib myprog.pl.

Для вашего веб-приложения, почему вы не делаете свою библиотеку относительно расположения самого скрипта? Затем просто установите его на каждом компьютере, где находятся библиотеки.

use FindBin;
use File::Spec::Functions;
use Cwd qw(abs_path getcwd);

BEGIN {
    my $curdir = getcwd;
    my $selfdir = $FindBin::Bin;
    my $libdir = abs_path(catdir($selfdir, 'lib'));

    chdir $libdir or die "can't chdir to $libdir: $@";
    use lib $libdir;
}

Конечно, самый простой вариант - не использовать разные каталоги lib. Почему вы не можете быть последовательными во всех своих средах?

Edit. Ваш комментарий: «Причина, по которой я вынужден использовать разные каталоги lib, заключается в том, что код, работающий на живом сайте, отличается от кода, работающего на бета-сайте ... в этом и заключается смысл иметь бета-сайт». - почему бы вам не справиться с этим на уровне установщика, вместо того, чтобы заставить сам код знать, является ли он живым по сравнению с бета-версией? например сохраняйте свой код в разных каталогах в вашем исходном дереве, как вы делаете сейчас, но устанавливайте только соответствующий код в каждую коробку. В конце концов, это именно то, что может сделать для вас хорошая система контроля версий - вы проверяете только одну ветку за раз, и вам следует устанавливать только одну версию кода за раз (как намекал Брайан Д Фой).

3 голосов
/ 11 ноября 2009

Я использую следующее во многих моих сценариях:

use strict;
use warnings;

use 5.008;

use FindBin;
use lib $FindBin::Bin;

Последняя строка может быть изменена следующим образом:

use FindBin;
use lib "$FindBin::Bin/lib";
2 голосов
/ 11 ноября 2009

Разные среды могут иметь разные настройки для переменной среды $PERL5LIB.

1 голос
/ 11 ноября 2009

Код, который вы показали, выглядит разумно. Вы можете установить одну копию этого кода в общесистемную папку, а затем код для ее вызова будет сводиться к

require '/path/to/findlib.pl';
findlib->import;

Форма require, которая принимает имя файла , а не поиск @INC.

В качестве альтернативы, если вы хотите изменить много вещей вокруг, вы можете посмотреть на развертывание приложения таким образом, чтобы оно было более удобным для local :: lib использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...