Как мой Perl-скрипт может найти свой модуль в том же каталоге? - PullRequest
47 голосов
/ 08 апреля 2009

Недавно я написал новый сценарий Perl для уничтожения процессов на основе имени процесса / имени пользователя и расширил его с помощью классов, чтобы я мог повторно использовать код процесса в других программах. Мой текущий макет -

/home/mutew/src/prod/pskill       <-- Perl script
/home/mutew/src/prod/Process.pm   <-- Package to handle process descriptions

Я добавил ~ / src / prod в переменную $ PATH для доступа к сценарию из любого места. При запуске сценария из любого каталога, кроме его резидентного каталога, возникает сообщение «Не удается найти Process.pm в @INC» (что вполне понятно, учитывая, что кроме общих каталогов в / usr, @INC включает только текущий каталог - ''). Один из обходных путей, который я использовал, - это директива use lib, поэтому -

use lib '/home/mutew/src/prod';

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


EDIT

  1. Я выбрал правильный ответ «depesz» из-за его простоты и использования основного модуля.
  2. Ответ Брайана Д Фоя, хотя и предлагает другие методы для достижения того же (TMTOWTDI), его вклад в perlfaq8 делает этот вопрос абсолютно излишним.

Ответы [ 9 ]

54 голосов
/ 16 сентября 2011

Мне любопытно, почему упрощенное решение

use File::Basename;
use lib dirname (__FILE__);
use SomeModuleLocatedInTheSameDirectoryAsThisPerlScriptOrModule;

не подошел. Модуль FindBin, похоже, имеет некоторые проблемы, если файл не является основным исполняемым Perl-скриптом, а просто неисполняемым Perl-модулем. По крайней мере, так я интерпретирую комментарий в документации . На самом деле не проверял.

Чтобы иметь любой другой путь относительно местоположения этого Perl-файла, сделайте что-то вроде

use File::Basename;
use lib dirname (__FILE__) . "/MyModules";
50 голосов
/ 08 апреля 2009

Самый простой подход, который я нашел, это использовать модуль FindBin. Как это:

use FindBin;
use lib $FindBin::Bin;

Обычно я предпочитаю, чтобы мои сценарии предоставлялись таким образом, чтобы программы находились в любом / bin, а библиотеки - в любом / lib

В этих ситуациях я использую немного более сложный подход:

use Cwd qw(abs_path);
use FindBin;
use lib abs_path("$FindBin::Bin/../lib");

Вызов abs_path должен заставить @INC содержать любой каталог / lib, а не / bin /../ lib - это всего лишь небольшое изменение, но облегчающее чтение сообщений об ошибках.

12 голосов
/ 08 апреля 2009

С perlfaq8 , что отвечает «Как добавить каталог к ​​моему пути включения (@INC) во время выполнения?» . Есть несколько других ответов на вопросы, связанные с этой проблемой.


Как добавить каталог к ​​моему пути включения (@INC) во время выполнения?

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

переменная среды PERLLIB

$ export PERLLIB=/path/to/my/dir
$ perl program.pl

переменная среды PERL5LIB

$ export PERL5LIB=/path/to/my/dir
$ perl program.pl

флаг командной строки perl -Idir

$ perl -I/path/to/my/dir program.pl

использование lib pragma:

use lib "$ENV{HOME}/myown_perllib";

Последнее особенно полезно, потому что оно знает о машинно-зависимых архитектурах. Прагматический модуль lib.pm был впервые включен в версию Perl 5.002.

3 голосов
/ 08 апреля 2009

Взгляните на Par :: Packer . Он создает исполняемый файл со всеми зависимостями скрипта. Это делает распространение легким. Вы также можете предоставить своим пользователям версию вашего модуля, которая может быть установлена ​​в их системах. См. Module :: Starter , где описан простой способ создания всех файлов, необходимых для стандартного распространения в стиле CPAN.

2 голосов
/ 12 октября 2017

Perl может выглядеть в любом каталоге, используя флаг -I. Здесь -I обозначает @INC, который является массивом путей, в которых perl ищет модули. Использование -I добавляет указанный путь к массиву @INC для этого выполнения.

Например:

perl -I lib bin/script.pl

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

Я знаю, что это работает для perl 5 . Я не уверен насчет других версий.

0 голосов
/ 16 октября 2018

Помимо уже заявленных решений:

  1. используйте FindBin / lib
  2. Perl Faq 8 Как добавить каталог к ​​моему пути включения (@INC) во время выполнения?

«Самый простой подход» (™), который я использую при разработке / тестировании модуля до для его развертывания (в / usr / local / lib / site_perl / или в другом месте в @INC) изменить @INC перед загрузкой модуля следующим образом:

#!/usr/bin/perl
use strict;
use warnings;
# Modify @INC prior to module loading.
BEGIN { unshift @INC, '.'; }
use YourModuleInCWD;

( Добавить текущий рабочий каталог в @INC? - PerlMonks )

0 голосов
/ 01 февраля 2016

Просто будь проще. Нет необходимости импортировать какие-либо библиотеки; просто узнайте свой текущий рабочий каталог:

use lib "$ENV{PWD}/relativ_path_own_perllib";

Для подобных проблем вы можете прочитать переменную окружения, которая дает информацию о том, где вы находитесь, ваш домашний каталог, содержимое операционной системы и т. Д., Всего с одной строкой программного кода в shell-терминале, например:

perl -e 'map { print; print " : ". $ENV{$_}." \n\r"; } sort keys %ENV '

Нет необходимости связывать некоторые библиотеки; просто используйте %ENV-Hash.

0 голосов
/ 10 сентября 2013

FindBin :: libs найдет всех ваших библиотек в разумных местах относительно пути, по которому работает ваш скрипт.

0 голосов
/ 09 апреля 2009

Чтобы преобразовать относительные ссылки в абсолютные и добавить в @INC, я обычно использую ex :: lib. Конечно, это полезно, только если вы планируете сохранять одинаковое расположение скрипта и модуля на всех машинах, где вы планируете запустить скрипт.

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