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.


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? ).


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.


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.