Bagaimana konstruksi @INC Perl? (alias Apa saja cara mempengaruhi di mana modul Perl dicari?)

199

Apa saja cara memengaruhi tempat modul Perl dicari? atau, Bagaimana Perl's @INC dibangun ?

Seperti yang kita ketahui, Perl menggunakan @INCarray yang berisi nama direktori untuk menentukan di mana mencari file modul Perl .

Tampaknya tidak ada posting tipe FAQ "@INC" yang komprehensif di StackOverflow, jadi pertanyaan ini dimaksudkan sebagai satu.

DVK
sumber
7
Ya, tapi ada yang sangat bagus di search.cpan.org/perldoc/… ?
mob
3
@mobrule: Saya tidak berpikir itu mendekati komprehensif - hanya mengatakan bagaimana menambahkan pada @INCsaat runtime, bukan konstruksi penuh.
Cascabel
2
@mobrule - @Jefromi menebak dengan benar - masalah utama dengan APAPUN dan semua referensi yang saya temukan sejauh ini adalah kurangnya info komprehensif tentang standar bin compile-in @ bin
DVK
3
Beberapa dapat menjadikan jawaban itu sebagai komprehensif dengan mengirimkan saya sebuah tambalan. Mudah karena perlfaq ada di Github. :)
brian d foy
1
Nah, "info komprehensif tentang kompilasi-in default @INC perl binary" adalah orang yang menyusunnya diatur. Jika Anda bertanya tentang berbagai jalur yang masuk ke sana, maka saya pikir Anda memiliki pertanyaan yang berbeda dari yang Anda jawab.
brian d foy

Jawaban:

254

Kami akan melihat bagaimana isi array ini dibangun dan dapat dimanipulasi untuk mempengaruhi di mana penerjemah Perl akan menemukan file-file modul.

  1. Default @INC

    Interpreter perl dikompilasi dengan @INCnilai default tertentu . Untuk mengetahui nilai ini, jalankan env -i perl -Vperintah ( env -iabaikan PERL5LIBvariabel lingkungan - lihat # 2) dan pada output Anda akan melihat sesuatu seperti ini:

    $ 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
     .

Catatan .di akhir; ini adalah direktori saat ini (yang tidak harus sama dengan direktori skrip). Itu hilang dalam Perl 5.26+, dan ketika Perl berjalan dengan -T(pemeriksaan noda diaktifkan) .

Untuk mengubah jalur default saat mengonfigurasi kompilasi biner Perl, tetapkan opsi konfigurasi otherlibdirs:

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

  1. Variabel lingkungan PERL5LIB(atauPERLLIB )

    Perl pra-pends @INCdengan daftar direktori (dipisahkan dengan titik dua) yang terkandung dalam PERL5LIB(jika tidak ditentukan, PERLLIBdigunakan) variabel lingkungan shell Anda. Untuk melihat konten variabel @INCafter PERL5LIBdan PERLLIBenvironment telah diterapkan, jalankan perl -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 opsi baris perintah

    Perl pra-pends @INCdengan daftar direktori (dipisahkan dengan titik dua) dilewatkan sebagai nilai -Iopsi baris perintah. Ini dapat dilakukan dengan tiga cara, seperti biasa dengan opsi Perl:

    • Lulus di baris perintah:

      perl -I /my/moduledir your_script.pl
    • Lulus melalui baris pertama (shebang) skrip Perl Anda:

      #!/usr/local/bin/perl -w -I /my/moduledir
    • Lulus sebagai bagian dari PERL5OPT(atau PERLOPT) variabel lingkungan (lihat bab 19.02 di Pemrograman Perl )

  3. Berikan itu melalui libpragma

    Perl pra-pends @INCdengan daftar direktori yang dikirimkan kepadanyause lib .

    Dalam sebuah program:

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

    Di baris perintah:

    perl -Mlib=/dir1,/dir2

    Anda juga dapat menghapus direktori dari @INCviano lib .

  4. Anda bisa langsung memanipulasi @INC sebagai array Perl biasa.

    Catatan: Karena @INCdigunakan selama fase kompilasi, ini harus dilakukan di dalam BEGIN {}blok, yang mendahului use MyModulepernyataan.

    • Tambahkan direktori ke awal via unshift @INC, $dir.

    • Tambahkan direktori ke bagian akhir via push @INC, $dir.

    • Lakukan hal lain yang dapat Anda lakukan dengan array Perl.

Catatan: Direktori tidak diubah ke @INCdalam urutan yang tercantum dalam jawaban ini, misalnya default @INCterakhir dalam daftar, didahului oleh PERL5LIB, didahului oleh -I, didahului oleh use libdan diarahkan@INC dimanipulasi , dua yang terakhir dicampur dalam urutan mana pun mereka berada dalam kode Perl.

Referensi:

Sepertinya tidak ada @INCposting tipe FAQ yang komprehensif di Stack Overflow, jadi pertanyaan ini dimaksudkan sebagai satu.

Kapan harus menggunakan setiap pendekatan?

  • Jika modul dalam direktori perlu digunakan oleh banyak / semua skrip di situs Anda, terutama dijalankan oleh banyak pengguna, direktori itu harus dimasukkan dalam default yang @INCdikompilasi ke biner Perl.

  • Jika modul dalam direktori akan digunakan secara eksklusif oleh pengguna tertentu untuk semua skrip yang dijalankan pengguna (atau jika mengkompilasi ulang Perl bukan opsi untuk mengubah default @INCdalam kasus penggunaan sebelumnya), atur pengguna PERL5LIB, biasanya selama login pengguna.

    Catatan: Perlu diketahui perangkap variabel lingkungan Unix yang biasa - misalnya dalam menjalankan skrip tertentu sebagai pengguna tertentu tidak menjamin menjalankannya dengan pengaturan lingkungan pengguna itu, misalnya via su.

  • Jika modul dalam direktori hanya perlu digunakan dalam keadaan tertentu (misalnya ketika skrip dieksekusi dalam mode pengembangan / debug, Anda dapat mengatur PERL5LIBsecara manual, atau meneruskan -Iopsi ke perl.

  • Jika modul hanya perlu digunakan untuk skrip tertentu, oleh semua pengguna yang menggunakannya, gunakan use lib/ no libpragma dalam program itu sendiri. Ini juga harus digunakan ketika direktori yang akan dicari harus ditentukan secara dinamis selama runtime - misalnya dari parameter baris perintah skrip atau jalur skrip (lihat modul FindBin untuk kasus penggunaan yang sangat bagus).

  • Jika direktori yang @INCperlu dimanipulasi sesuai dengan beberapa logika yang rumit, tidak mungkin terlalu sulit untuk diterapkan dengan kombinasi use lib/ no libpragma, maka gunakan @INCmanipulasi langsung di dalam BEGIN {}blok atau di dalam perpustakaan tujuan khusus yang ditunjuk untuk@INC manipulasi, yang harus digunakan oleh skrip Anda (s) sebelum modul lain digunakan.

    Contoh dari hal ini adalah secara otomatis beralih antar perpustakaan dalam direktori prod / uat / dev, dengan pickup perpustakaan air terjun di prod jika hilang dari dev dan / atau UAT (kondisi terakhir membuat solusi standar "gunakan lib + FindBin" cukup rumit. A ilustrasi rinci dari skenario ini adalah di Bagaimana cara menggunakan modul Perl beta dari skrip Perl beta? .

  • Kasus penggunaan tambahan untuk memanipulasi secara langsung @INCadalah untuk dapat menambahkan referensi subrutin atau referensi objek (ya, Virginia, @INCdapat berisi kode Perl khusus dan bukan hanya nama direktori, seperti yang dijelaskan dalam Kapan referensi subrutin dalam @INC disebut? ).

DVK
sumber
1
jangan lupa PERLOPT, di mana Anda dapat mengatur -I. Juga, hal-hal seperti base.pm dan local :: lib menggunakan hal-hal yang Anda cantumkan secara implisit.
brian d foy
1
@brian - use :: base menggunakannya karena "membutuhkan" di bawahnya, IIRC. Saya tidak terbiasa dengan local :: lib, perlu membaca lebih banyak untuk memahami apa itu
DVK
3
Juga, untuk membuat ini jawaban yang sangat bagus, Anda harus memberi tahu orang-orang kapan mereka harus menggunakan masing-masing. Hanya memberi mereka 10 pilihan tentang bagaimana mereka bisa sangat tidak membantu. :)
brian d foy
PS Siapa pun, silakan sunting jawaban untuk memasukkan inklusi direktori khusus arsitektur kedua melalui -I / use lib. Saya berencana untuk melakukannya sendiri di lain waktu tetapi harus offline sekarang.
DVK
@brian - menambahkan PERLOPT. Saya merasa ingin menyebutkan item base.pm dan "kapan @INC terbiasa" lainnya lebih cocok dengan @ INC / mencari file modul FAQ yang saya pasang dan ditautkan dari sini, jadi saya taruh di sana.
DVK
18

Selain lokasi yang tercantum di atas, versi OS X dari Perl juga memiliki dua cara lagi:

  1. File /Library/Perl/x.xx/AppendToPath. Jalur yang tercantum dalam file ini ditambahkan ke @INC saat runtime.

  2. File /Library/Perl/x.xx/PrependToPath. Jalur yang tercantum dalam file ini ditambahkan ke @INC saat runtime.

dgatwood
sumber
6

Seperti yang sudah dikatakan @INC adalah array dan Anda bebas untuk menambahkan apa pun yang Anda inginkan.

Script CGI REST saya terlihat seperti:

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

Subroutine yang hilang diekspor oleh Rest.pm.

Kacper Perschke
sumber