@INC của Perl được xây dựng như thế nào? (aka Tất cả các cách ảnh hưởng đến nơi các mô-đun Perl được tìm kiếm là gì?)


199

Tất cả các cách ảnh hưởng đến nơi các mô-đun Perl được tìm kiếm là gì? hoặc, @INC của Perl được xây dựng như thế nào?

Như chúng ta biết, Perl sử dụng @INCmảng chứa tên thư mục để xác định nơi tìm kiếm tệp mô-đun Perl .

Dường như không có bài đăng Câu hỏi thường gặp "@INC" toàn diện trên StackOverflow, vì vậy câu hỏi này được dự định là một.


7
Vâng, nhưng có một thứ hoàn toàn tốt tại search.cpan.org/perldoc/ ,?
mob

3
@mobrule: Tôi không nghĩ rằng bất cứ nơi nào gần như toàn diện - nó chỉ nói về cách thêm vào @INClúc chạy chứ không phải toàn bộ cấu trúc.
Cascabel

2
@mobrule - @Jefromi đoán đúng - vấn đề chính với BẤT K and và tất cả các tài liệu tham khảo tôi tìm thấy cho đến nay là thiếu thông tin toàn diện về perl binary được biên dịch mặc định @INC
DVK

3
Một số có thể làm cho câu trả lời đó là toàn diện bằng cách gửi cho tôi một bản vá. Thật dễ dàng vì perlfaq có trong Github. :)
brian d foy

1
Chà, "thông tin toàn diện về perl binary được biên dịch mặc định @INC" là nó là người đã biên soạn nó. Nếu bạn hỏi về những con đường khác nhau đi vào đó, thì tôi nghĩ bạn có một câu hỏi khác với câu hỏi bạn đã trả lời.
brian d foy

Câu trả lời:


254

Chúng tôi sẽ xem xét cách các nội dung của mảng này được xây dựng và có thể được thao tác để ảnh hưởng đến nơi trình thông dịch Perl sẽ tìm thấy các tệp mô-đun.

  1. Mặc định @INC

    Trình thông dịch Perl được biên dịch với một @INCgiá trị mặc định cụ thể . Để tìm ra giá trị này, hãy chạy env -i perl -Vlệnh ( env -ibỏ qua PERL5LIBbiến môi trường - xem # 2) và trong đầu ra, bạn sẽ thấy một cái gì đó như thế này:

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

Lưu ý .ở cuối; đây là thư mục hiện tại (không nhất thiết phải giống với thư mục của tập lệnh). Nó bị thiếu trong Perl 5.26+ và khi Perl chạy với -T(bật kiểm tra mờ ) .

Để thay đổi đường dẫn mặc định khi định cấu hình biên dịch nhị phân Perl, hãy đặt tùy chọn cấu hình otherlibdirs:

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

  1. Biến môi trường PERL5LIB(hoặc PERLLIB)

    Perl trả trước @INCvới một danh sách các thư mục (được phân tách bằng dấu hai chấm) có trong PERL5LIB(nếu nó không được xác định, PERLLIBđược sử dụng) biến môi trường của trình bao của bạn. Để xem nội dung của các biến @INCsau PERL5LIBPERLLIBmôi trường đã có hiệu lực, hãy chạy 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 tùy chọn dòng lệnh

    Perl trả trước @INCvới một danh sách các thư mục (được phân tách bằng dấu hai chấm) được truyền dưới dạng giá trị của -Itùy chọn dòng lệnh. Điều này có thể được thực hiện theo ba cách, như thường lệ với các tùy chọn Perl:

    • Vượt qua nó trên dòng lệnh:

      perl -I /my/moduledir your_script.pl
    • Truyền nó qua dòng đầu tiên (shebang) của tập lệnh Perl của bạn:

      #!/usr/local/bin/perl -w -I /my/moduledir
    • Vượt qua nó như một phần của PERL5OPT(hoặc PERLOPT) biến môi trường (xem chương 19.02 trong Lập trình Perl )

  3. Vượt qua nó thông qua libpragma

    Perl trả trước @INCvới một danh sách các thư mục được truyền vào nó thông qua use lib.

    Trong một chương trình:

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

    Trên dòng lệnh:

    perl -Mlib=/dir1,/dir2

    Bạn cũng có thể loại bỏ các thư mục từ @INCthông quano lib .

  4. Bạn có thể thao tác trực tiếp @INCnhư một mảng Perl thông thường.

    Lưu ý: Vì @INCđược sử dụng trong giai đoạn biên dịch, điều này phải được thực hiện bên trong một BEGIN {}khối, trước use MyModulecâu lệnh.

    • Thêm thư mục vào đầu thông qua unshift @INC, $dir.

    • Thêm thư mục vào cuối thông qua push @INC, $dir.

    • Làm bất cứ điều gì khác bạn có thể làm với một mảng Perl.

Lưu ý: Các thư mục được unshifted lên @INCtheo thứ tự được liệt kê trong câu trả lời này, ví dụ như mặc định @INClà cuối cùng trong danh sách, trước bởi PERL5LIB, trước bởi -I, trước bằng use libvà trực tiếp @INCthao tác, sau này hai trộn lẫn trong bất cứ đặt họ trong mã Perl.

Người giới thiệu:

Dường như không có @INCbài đăng loại FAQ toàn diện trên Stack Overflow, vì vậy câu hỏi này được dự định là một.

Khi nào nên sử dụng từng phương pháp?

  • Nếu các mô-đun trong một thư mục cần được sử dụng bởi nhiều / tất cả các tập lệnh trên trang web của bạn, đặc biệt được điều hành bởi nhiều người dùng, thư mục đó sẽ được đưa vào mặc định @INCđược biên dịch thành nhị phân Perl.

  • Nếu các mô-đun trong thư mục sẽ được sử dụng riêng bởi một người dùng cụ thể cho tất cả các tập lệnh mà người dùng chạy (hoặc nếu biên dịch lại Perl không phải là một tùy chọn để thay đổi mặc định @INCtrong trường hợp sử dụng trước đó) PERL5LIB, thường là trong quá trình đăng nhập của người dùng.

    Lưu ý: Xin lưu ý các cạm bẫy biến môi trường Unix thông thường - ví dụ: trong một số trường hợp nhất định chạy tập lệnh vì người dùng cụ thể không đảm bảo chạy chúng với môi trường của người dùng đó được thiết lập, ví dụ như thông qua su.

  • Nếu các mô-đun trong thư mục chỉ cần được sử dụng trong các trường hợp cụ thể (ví dụ: khi tập lệnh được thực thi ở chế độ phát triển / gỡ lỗi, bạn có thể đặt PERL5LIBthủ công hoặc chuyển -Itùy chọn sang perl.

  • Nếu các mô-đun chỉ cần được sử dụng cho các tập lệnh cụ thể, bởi tất cả người dùng sử dụng chúng, hãy sử dụng use lib/ no libpragmas trong chính chương trình. Nó cũng nên được sử dụng khi thư mục cần tìm kiếm cần được xác định động trong thời gian chạy - ví dụ: từ các tham số dòng lệnh hoặc đường dẫn của tập lệnh (xem mô-đun FindBin để biết trường hợp sử dụng rất hay).

  • Nếu các thư mục @INCcần được thao tác theo một số logic phức tạp, không thể quá khó sử dụng bằng cách kết hợp use lib/ no libpragmas, thì hãy sử dụng @INCthao tác trực tiếp bên trong BEGIN {}khối hoặc bên trong thư viện mục đích đặc biệt được chỉ định để @INCthao tác, phải được sử dụng bởi tập lệnh của bạn (s) trước khi bất kỳ mô-đun khác được sử dụng.

    Một ví dụ về điều này là tự động chuyển đổi giữa các thư viện trong các thư mục prod / uat / dev, với việc lấy thư viện thác nước trong prod nếu nó bị thiếu từ dev và / hoặc UAT (điều kiện cuối cùng làm cho giải pháp "sử dụng lib + FindBin" tiêu chuẩn khá phức tạp. minh họa chi tiết cho kịch bản này là trong Làm cách nào để sử dụng các mô-đun Perl beta từ các tập lệnh beta Perl ? .

  • Một trường hợp sử dụng bổ sung để thao tác trực tiếp @INClà có thể thêm các tham chiếu chương trình con hoặc tham chiếu đối tượng (vâng, Virginia, @INCcó thể chứa mã Perl tùy chỉnh và không chỉ tên thư mục, như được giải thích trong Khi nào là tham chiếu chương trình con trong @INC được gọi? ).


1
đừng quên PERLOPT, nơi bạn có thể đặt -I. Ngoài ra, những thứ như base.pm và local :: lib sử dụng những thứ bạn đã liệt kê ngầm.
brian d foy

1
@brian - use :: base sử dụng nó do "yêu cầu" bên dưới, IIRC. Tôi không quen thuộc với local :: lib, sẽ cần đọc thêm để hiểu nội dung của nó
DVK

3
Ngoài ra, để làm cho câu trả lời này thực sự tốt, bạn cần nói với mọi người khi nào họ nên sử dụng từng câu hỏi. Chỉ cần cung cấp cho họ 10 tùy chọn về cách họ có thể không hữu ích. :)
brian d foy

PS Bất cứ ai, xin vui lòng chỉnh sửa câu trả lời để bao gồm một thư mục cụ thể theo kiến ​​trúc thứ hai thông qua -I / use lib. Tôi đã lên kế hoạch để thực hiện điều đó sau đó nhưng cần phải ngoại tuyến ngay bây giờ.
DVK

@brian - thêm PERLOPT. Tôi cảm thấy muốn đề cập đến các mục base.pm và các mục "khi nào @INC được sử dụng" phù hợp hơn với @ INC / tìm tệp mô-đun Câu hỏi thường gặp tôi đã đăng và liên kết từ đây, vì vậy tôi đặt nó ở đó.
DVK

18

Ngoài các vị trí được liệt kê ở trên, phiên bản OS X của Perl còn có hai cách khác:

  1. Tệp /L Library / Coller / x.xx / AppendToPath. Các đường dẫn được liệt kê trong tệp này được gắn vào @INC khi chạy.

  2. Tệp /L Library / Coller / x.xx / RependToPath. Các đường dẫn được liệt kê trong tệp này được thêm vào @INC khi chạy.


6

Như đã nói, @INC là một mảng và bạn có thể tự do thêm bất cứ thứ gì bạn muốn.

Kịch bản CGI REST của tôi trông giống như:

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

Chương trình con đã biến mất được xuất bởi Rest.pm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.