[perl] Perl의 @INC는 어떻게 구성됩니까? (aka Perl 모듈 검색 위치에 영향을 미치는 모든 방법은 무엇입니까?)

Perl 모듈의 검색 위치에 영향을 미치는 모든 방법은 무엇입니까? 또는 Perl의 @INC는 어떻게 구성 됩니까?

아시다시피 Perl은 @INC디렉토리 이름이 포함 된 배열을 사용 하여 Perl 모듈 파일을 검색 할 위치를 결정합니다 .

StackOverflow에 대한 포괄적 인 “@INC”FAQ 유형 게시물이없는 것 같으므로이 질문은 하나입니다.



답변

우리는이 배열의 내용이 어떻게 구성되고 Perl 인터프리터가 모듈 파일을 찾는 지에 영향을주기 위해 조작 될 수있는 방법을 살펴볼 것입니다.

  1. 기본 @INC

    Perl 인터프리터는 특정 @INC기본값으로 컴파일됩니다 . 이 값을 찾으려면 env -i perl -Vcommand를 실행 ( 환경 변수 env -i무시 PERL5LIB-# 2 참조)하면 출력에 다음과 같은 내용이 표시됩니다.

    $ env -i perl -V
    ...
    @INC:
     /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/site_perl/5.18.0
     /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/5.18.0
     .
    

.끝에 주의하십시오 ; 이것이 현재 디렉토리입니다 (스크립트의 디렉토리와 반드시 같을 필요는 없음). Perl 5.26+ 및 Perl이 -T(taint checks enabled)로 실행될 때 누락되었습니다 .

Perl 바이너리 컴파일을 구성 할 때 기본 경로를 변경하려면 구성 옵션을 설정하십시오 otherlibdirs.

Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3

  1. 환경 변수 PERL5LIB(또는 PERLLIB)

    Perl 은 쉘의 환경 변수 ( 정의되지 않은 경우 사용됨)에 @INC포함 된 디렉토리 목록 (콜론으로 구분)을 앞에 추가 합니다. after 및 environment 변수 의 내용이 적용되었는지 확인하려면을 실행하십시오 .PERL5LIBPERLLIB@INCPERL5LIBPERLLIBperl -V

    $ perl -V
    ...
    %ENV:
      PERL5LIB="/home/myuser/test"
    @INC:
     /home/myuser/test
     /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/site_perl/5.18.0
     /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/5.18.0
     .
    
  2. -I 명령 줄 옵션

    Perl @INC-I명령 행 옵션의 값으로 전달 된 디렉토리 목록 (콜론으로 구분)을 앞에 추가합니다. 이는 Perl 옵션에서 평소와 같이 세 가지 방법으로 수행 할 수 있습니다.

    • 명령 행에 전달하십시오.

      perl -I /my/moduledir your_script.pl
    • Perl 스크립트의 첫 번째 줄 (shebang)을 통해 전달하십시오.

      #!/usr/local/bin/perl -w -I /my/moduledir
    • 환경 변수의 일부로 전달하십시오 PERL5OPT(또는 프로그래밍 Perl의PERLOPT 19.02 장 참조 )

  3. pragma 를 통해 전달lib

    Perl @INC은을 통해 전달 된 디렉토리 목록 앞에 붙 습니다 use lib.

    프로그램에서 :

    use lib ("/dir1", "/dir2");

    명령 행에서 :

    perl -Mlib=/dir1,/dir2

    @INC통해 디렉토리를 제거no lib 할 수도 있습니다 .

  4. @INC일반 Perl 배열로 직접 조작 할 수 있습니다 .

    참고 : @INC컴파일 단계에서 사용 되므로 BEGIN {}블록 앞에 수행해야합니다 use MyModule.

    • 를 통해 처음에 디렉토리를 추가하십시오 unshift @INC, $dir.

    • 를 통해 디렉토리를 끝에 추가하십시오 push @INC, $dir.

    • Perl 배열로 할 수있는 다른 작업을 수행하십시오.

참고 : 디렉토리가되는 시프트되지@INC예를 들어 기본적으로,이 답변에 나열된 순서 @INC로 시작, 목록의 마지막 PERL5LIB앞에, -I, 앞에 use lib직접 @INC그들이 펄 코드에 주문 중의 조작은, 뒤의 두 혼합.

참고 문헌 :

@INCStack Overflow에 대한 포괄적 인 FAQ 유형 게시물 이없는 것 같으므로이 질문은 하나입니다.

각 방법을 언제 사용해야합니까?

  • 디렉토리의 모듈이 사이트의 많은 / 모든 스크립트, 특히 여러 사용자가 실행해야하는 경우 해당 디렉토리는 @INCPerl 바이너리로 컴파일 된 기본값에 포함되어야합니다 .

  • 디렉토리의 모듈이 사용자가 실행하는 모든 스크립트에 대해 특정 사용자가 독점적으로 사용하는 경우 (또는 Perl을 재 컴파일하는 것이 @INC이전 사용 사례에서 기본값을 변경하는 옵션이 아닌 경우) PERL5LIB, 일반적으로 사용자 로그인 중에 users ‘를 설정하십시오 .

    참고 : 일반적인 Unix 환경 변수 함정에주의하십시오. 예를 들어 특정 사용자가 스크립트를 실행한다고해서 해당 사용자 환경이 설정된 상태에서 스크립트를 실행한다고 보증 할 수는 없습니다 (예 : via) su.

  • 디렉토리의 모듈을 특정 상황에서만 사용해야하는 경우 (예 : 개발 / 디버그 모드에서 스크립트를 실행할 때) PERL5LIB수동으로 설정 하거나 -I옵션을 perl로 전달할 수 있습니다 .

  • 모듈을 특정 스크립트에만 사용해야하는 경우 모든 사용자 가 모듈을 사용하는 경우 프로그램 자체에서 use lib/ no libpragma를 사용하십시오. 스크립트의 명령 행 매개 변수 또는 스크립트 경로와 같이 런타임 중에 검색 할 디렉토리를 동적으로 결정해야하는 경우에도 사용해야합니다 ( 유용한 사례 는 FindBin 모듈 참조 ).

  • / pragma의 @INC조합으로 구현하기에 너무 복잡하지 않은 일부 복잡한 논리에 따라 디렉토리를 조작 해야하는 경우 블록 내부 또는 조작 을 위해 지정된 특수 목적 라이브러리 내에서 직접 조작 을 사용 하십시오.이 스크립트는 스크립트에서 사용해야합니다 다른 모듈을 사용하기 전에use libno lib@INCBEGIN {}@INC

    예를 들어, prod / uat / dev 디렉토리의 라이브러리 사이를 자동으로 전환하고 dev 및 / 또는 UAT에서 누락 된 폭포 라이브러리를 prod로 가져옵니다 (마지막 조건은 표준 “use lib + FindBin”솔루션을 상당히 복잡하게 만듭니다). 이 시나리오에 대한 자세한 설명은 베타 Perl 스크립트에서 베타 Perl 모듈을 어떻게 사용합니까?에 있습니다.

  • 직접 조작을위한 추가 사용 사례는 @INC서브 루틴 참조 또는 객체 참조를 추가 할 수있는 것입니다 (예, Virginia 는 @INC의 서브 루틴 참조는 언제 호출됩니까?에@INC 설명 된대로 디렉토리 이름뿐만 아니라 사용자 정의 Perl 코드를 포함 할 수 있음 ).


답변

위에 나열된 위치 외에도 Perl의 OS X 버전에는 두 가지 방법이 더 있습니다.

  1. /Library/Perl/x.xx/AppendToPath 파일 이 파일에 나열된 경로는 런타임시 @INC에 추가됩니다.

  2. /Library/Perl/x.xx/PrependToPath 파일 이 파일에 나열된 경로는 런타임시 @INC 앞에 추가됩니다.


답변

이미 말했듯이 @INC는 배열이며 원하는 것을 자유롭게 추가 할 수 있습니다.

내 CGI REST 스크립트는 다음과 같습니다.

#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
    push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);

사라진 서브 루틴은 Rest.pm에 의해 내보내집니다.


답변