@INC ของ Perl สร้างขึ้นอย่างไร (aka ทุกวิธีที่มีผลต่อการค้นหาโมดูล Perl คืออะไร?)


199

มีวิธีใดบ้างที่จะส่งผลต่อการค้นหาโมดูล Perl หรือวิธีสร้าง @INC ของ Perl เป็นอย่างไร

ดังที่เราทราบPerl ใช้@INCอาร์เรย์ที่มีชื่อไดเรกทอรีเพื่อกำหนดว่าจะค้นหาไฟล์โมดูล Perlได้ที่ไหน

ดูเหมือนจะไม่มีโพสต์ประเภทคำถามที่พบบ่อย "@ INC" ที่ครอบคลุมใน StackOverflow ดังนั้นคำถามนี้มีจุดมุ่งหมายเดียว


7
ใช่ แต่มีสิ่งที่ดีอย่างสมบูรณ์ในsearch.cpan.org/perldoc/ ​​...... ?
ม็อบ

3
@mobrule: ฉันไม่คิดว่ามันจะอยู่ใกล้แค่เอื้อม - มันเป็นเพียงการบอกวิธีการเพิ่มไปยัง@INCรันไทม์ไม่ใช่การก่อสร้างเต็มรูปแบบ
Cascabel

2
@mobrule - @Jefromi คาดเดาถูกต้อง - ปัญหาหลักของ ANY และการอ้างอิงทั้งหมดที่ฉันพบคือการขาดข้อมูลที่ครอบคลุมเกี่ยวกับค่าเริ่มต้นที่คอมไพล์ในไบนารีของ perl @INC
DVK

3
บางคนสามารถให้คำตอบที่ครอบคลุมโดยส่งแพทช์ให้ฉัน มันง่ายเพราะ perlfaq อยู่ใน Github :)
brian d foy

1
"ข้อมูลที่ครอบคลุมเกี่ยวกับค่าเริ่มต้นที่คอมไพล์ในไบนารีของ Perl คือ @INC" คือมันเป็นบุคคลที่รวบรวมไว้ หากคุณถามเกี่ยวกับเส้นทางต่าง ๆ ที่เข้ามาฉันคิดว่าคุณมีคำถามที่แตกต่างจากที่คุณตอบ
brian d foy

คำตอบ:


254

เราจะดูว่าเนื้อหาของอาเรย์นี้ถูกสร้างขึ้นและสามารถจัดการให้มีผลกระทบต่อที่ล่าม Perl จะหาไฟล์โมดูล

  1. ค่าเริ่มต้น @INC

    ล่าม Perl จะรวบรวมกับเฉพาะ@INCค่าเริ่มต้น เพื่อหาค่านี้เรียกใช้env -i perl -Vคำสั่ง ( 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

หากต้องการเปลี่ยนเส้นทางเริ่มต้นเมื่อกำหนดค่าการรวบรวมไบนารี Perl ให้ตั้งค่าตัวเลือกการกำหนดค่าotherlibdirs:

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

  1. ตัวแปรสภาพแวดล้อมPERL5LIB(หรือPERLLIB)

    Perl pre-pends @INCพร้อมกับรายการไดเรกทอรี (คั่นด้วยโคลอน) ที่มีอยู่ในตัวแปรสภาพแวดล้อมPERL5LIB(ถ้าไม่ได้กำหนด, PERLLIBใช้) ของเชลล์ของคุณ หากต้องการดูเนื้อหาของ@INCหลังPERL5LIBและตัวแปรสภาพแวดล้อมได้นำผลการทำงานPERLLIBperl -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
    • ส่งผ่านบรรทัดแรก (shebang) ของสคริปต์ Perl ของคุณ:

      #!/usr/local/bin/perl -w -I /my/moduledir
    • ผ่านมันเป็นส่วนหนึ่งของPERL5OPT(หรือPERLOPT) ตัวแปรสภาพแวดล้อม (ดูบทที่ 19.02 ในการเขียนโปรแกรม Perl )

  3. ส่งผ่านทางlibpragma

    Perl pre-pends @INCกับรายชื่อของไดเรกทอรีที่ส่งผ่านไปยังมันผ่านuse libที่มีรายชื่อของไดเรกทอรีผ่านไปผ่าน

    ในโปรแกรม:

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

    บนบรรทัดคำสั่ง:

    perl -Mlib=/dir1,/dir2

    นอกจากนี้คุณยังสามารถลบไดเรกทอรีจาก@INCno libผ่าน

  4. คุณสามารถจัดการโดยตรง@INCเป็นอาร์เรย์ Perl ปกติ

    หมายเหตุ: เนื่องจาก@INCถูกใช้ในระหว่างขั้นตอนการรวบรวมสิ่งนี้จะต้องทำภายในBEGIN {}บล็อกซึ่งนำหน้าuse MyModuleคำสั่ง

    • unshift @INC, $dirเพิ่มไดเรกทอรีที่จุดเริ่มต้นผ่าน

    • push @INC, $dirเพิ่มไดเรกทอรีไปยังจุดสิ้นสุดผ่าน

    • ทำอะไรก็ได้ที่คุณสามารถทำได้กับอาร์เรย์ Perl

หมายเหตุ: ไดเรกทอรีจะไม่ถูกเลื่อนลง@INCในลำดับที่ระบุไว้ในคำตอบนี้เช่นค่าเริ่มต้น@INCจะอยู่ในรายการก่อนPERL5LIBหน้าโดย-Iนำหน้านำหน้านำโดยuse libและโดยตรง@INCการจัดการที่สองหลังผสมในแล้วแต่จำนวนใดจะสั่งพวกเขาอยู่ในรหัส Perl

อ้างอิง:

ดูเหมือนจะไม่มีการ@INCโพสต์ประเภทคำถามที่พบบ่อยที่ครอบคลุมในกองล้นดังนั้นคำถามนี้มีวัตถุประสงค์เป็นหนึ่ง

ควรใช้แต่ละวิธีเมื่อใด

  • หากจำเป็นต้องใช้โมดูลในไดเรกทอรีโดยสคริปต์จำนวนมาก / ทั้งหมดบนเว็บไซต์ของคุณโดยเฉพาะผู้ใช้หลายรายที่เรียกใช้ไดเรกทอรีนั้นควรรวมอยู่ในค่าเริ่มต้นที่@INCรวบรวมไว้ในไบนารี Perl

  • หากโมดูลในไดเรกทอรีจะถูกใช้โดยผู้ใช้เฉพาะสำหรับสคริปต์ทั้งหมดที่ผู้ใช้เรียกใช้ (หรือหากการคอมไพล์ซ้ำ Perl ไม่ใช่ตัวเลือกในการเปลี่ยนค่าเริ่มต้น@INCในกรณีการใช้งานก่อนหน้านี้) ให้ตั้งค่าของผู้PERL5LIBใช้

    หมายเหตุ: โปรดระวังปกติ Unix ผิดพลาดตัวแปรสภาพแวดล้อม - suเช่นในบางกรณีการทำงานสคริปต์ในฐานะผู้ใช้โดยเฉพาะอย่างยิ่งไม่ได้รับประกันการทำงานพวกเขากับสภาพแวดล้อมของผู้ใช้ตั้งค่าเช่นผ่านทาง

  • หากจำเป็นต้องใช้โมดูลในไดเรกทอรีเฉพาะในสถานการณ์ที่เฉพาะเจาะจง (เช่นเมื่อสคริปต์ถูกดำเนินการในโหมดการพัฒนา / การดีบักคุณสามารถตั้งค่าPERL5LIBด้วยตนเองหรือส่ง-Iตัวเลือกไปยัง Perl

  • หากจำเป็นต้องใช้โมดูลสำหรับสคริปต์เฉพาะโดยผู้ใช้ทุกคนใช้ให้ใช้use lib/ no libpragmas ในโปรแกรมเอง นอกจากนี้ควรใช้เมื่อไดเรกทอรีที่จะค้นหาต้องถูกกำหนดแบบไดนามิกระหว่างรันไทม์ - เช่นจากพารามิเตอร์บรรทัดคำสั่งของสคริปต์หรือเส้นทางของสคริปต์ (ดูโมดูลFindBinสำหรับกรณีการใช้งานที่ดีมาก)

  • หากไดเรกทอรีที่@INCจำเป็นต้องจัดการตามตรรกะที่ซับซ้อนบางอย่างเป็นไปไม่ได้ที่จะใช้ความพยายามมากเกินไปโดยการรวมกันของuse lib/ no libpragmas จากนั้นใช้การ@INCจัดการโดยตรงในBEGIN {}บล็อกหรือในห้องสมุดวัตถุประสงค์พิเศษที่กำหนดไว้สำหรับ@INCจัดการ (s) ก่อนที่จะใช้โมดูลอื่น ๆ

    ตัวอย่างของสิ่งนี้คือการสลับระหว่างไลบรารีในไดเร็กทอรี prod / uat / dev โดยอัตโนมัติด้วย Waterfall library pickup ใน prod หากมันหายไปจาก dev และ / หรือ UAT (เงื่อนไขสุดท้ายทำให้โซลูชัน "ใช้ lib + FindBin" มาตรฐานค่อนข้างซับซ้อน A ภาพประกอบรายละเอียดของสถานการณ์นี้อยู่ในฉันจะใช้โมดูล Perl เบต้าจากสคริปต์ Perl เบต้า?

  • กรณีการใช้งานเพิ่มเติมสำหรับการจัดการโดยตรง@INCคือสามารถเพิ่มการอ้างอิงรูทีนย่อยหรือการอ้างอิงวัตถุ (ใช่เวอร์จิเนีย@INCสามารถมีโค้ด Perl ที่กำหนดเองและไม่เพียงแค่ชื่อไดเรกทอรีตามที่อธิบายไว้ในเมื่อมีการอ้างอิงรูทีนย่อยใน @INC เรียกว่า? )


1
อย่าลืม PERLOPT ที่คุณสามารถตั้งค่า -I นอกจากนี้สิ่งต่าง ๆ เช่น base.pm และ local :: lib ใช้สิ่งที่คุณแสดงรายการโดยนัย
brian d foy

1
@brian - use :: base ใช้เนื่องจาก "ต้องการ" ภายใต้ IIRC ฉันไม่คุ้นเคยกับท้องถิ่น :: lib จะต้องอ่านเพิ่มเติมเพื่อเข้าใจว่ามันเกี่ยวกับอะไร
DVK

3
นอกจากนี้เพื่อให้เป็นคำตอบที่ดีมากคุณต้องบอกผู้คนเมื่อพวกเขาควรใช้แต่ละคน เพียงแค่ให้ทางเลือกแก่พวกเขา 10 วิธีว่าพวกเขาจะไม่มีประโยชน์ :)
brian d foy

PS ใครก็ตามโปรดแก้ไขคำตอบเพื่อรวมไดเรกทอรีเฉพาะสถาปัตยกรรมที่สองผ่าน -I / use lib ฉันวางแผนที่จะทำเองในภายหลัง แต่ต้องออฟไลน์ก่อน
DVK

@brian - เพิ่ม PERLOPT ฉันรู้สึกว่าการกล่าวถึง base.pm และรายการอื่น ๆ ของ @INC เมื่อใช้แล้วจะเหมาะกับ @ INC / การหาไฟล์โมดูลคำถามที่พบบ่อยฉันโพสต์และเชื่อมโยงจากที่นี่ดังนั้นฉันจึงวางไว้ที่นั่น
DVK

18

นอกจากตำแหน่งที่ระบุไว้ข้างต้นแล้วเวอร์ชันของ OS X ของ Perl ยังมีอีกสองวิธี:

  1. ไฟล์ /Library/Perl/x.xx/AppendToPath เส้นทางที่ระบุไว้ในไฟล์นี้จะถูกผนวกเข้ากับ @INC ตอนรันไทม์

  2. ไฟล์ /Library/Perl/x.xx/PrependToPath พา ธ ที่แสดงรายการในไฟล์นี้จะถูกต่อท้ายเป็น @INC ตอนรันไทม์


6

ตามที่ได้กล่าวไปแล้ว @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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.