2010-03-26 11 views
13

Nếu chương trình Perl của tôi sử dụng các mô-đun Perl, làm cách nào để xác định nơi tìm tệp có chứa mã mô-đun?Làm cách nào để chương trình Perl biết nơi tìm tệp chứa mô-đun Perl mà nó sử dụng?

Ví dụ, nếu chương trình bao gồm:

use MyModule1;    # Example 1 
use This::Here::MyModule2; # Example 2 

nó sẽ tìm ở đâu?

+0

Tôi không thể tìm thấy câu trả lời toàn diện cho câu hỏi này trên SO mà tôi có thể liên kết đến, vì vậy tôi quyết định tạo một câu hỏi. Nếu câu trả lời được cung cấp dưới đây là cần bổ sung/sửa chữa, xin vui lòng có nó :) – DVK

Trả lời

13

Trình thông dịch Perl (chạy chương trình perl của bạn) sẽ sử dụng một mảng đặc biệt gọi là @INC để tìm kiếm tệp chứa mô-đun.

Mỗi giá trị trong mảng @INC là tên thư mục (nhưng xem ghi chú bên dưới); Perl sẽ tìm kiếm trong các thư mục đó trong vòng lặp bằng cách sử dụng các quy tắc được chỉ định bên dưới. (Vui lòng tham khảo this SO post for details of how the contents of @INC are determined).

Nếu không tìm thấy tệp của mô-đun sau khi hết @INC, quá trình biên dịch của chương trình sẽ bị hủy bỏ do lỗi. Nếu tìm thấy tệp của mô-đun trong một trong các thư mục được chỉ định trong @INC, tìm kiếm được hoàn tất mà không cần xem phần còn lại của @INC.

Cách Perl tìm kiếm một tập tin mô-đun trong mỗi thư mục được liệt kê trong @INC là như sau:

  • Đầu tiên, nó sẽ tách thành phần thứ bậc tên mô-đun của (từ cách nhau bởi ::), vào thành phần cuối cùng - sẽ được sử dụng để tạo thành tên tệp - và đường dẫn phân cấp (tất cả các thành phần nằm trước :: cuối cùng).

    Trong trường hợp tên mô-đun chỉ có một thành phần (không có ::, ví dụ: MyModule1 ở trên), đường dẫn phân cấp trống và tên tệp là tên của mô-đun. Trong ví dụ thứ hai trong câu hỏi này, thành phần cuối cùng là MyModule2 và đường dẫn phân cấp sẽ là This::Here.

  • Tên tệp dự kiến ​​sẽ được xác định bằng cách nối thành phần cuối cùng của tên mô-đun với tiện ích mở rộng .pm. Ví dụ. MyModule1.pmMyModule2.pm trong các ví dụ của chúng tôi.

    LƯU Ý: Tên mô-đun rõ ràng là phân biệt chữ hoa chữ thường trên Unix và các hệ điều hành khác nơi đặt tên tệp/thư mục phân biệt chữ hoa chữ thường.

  • thư mục của module sẽ được xác định bởi:

    1. Lấy danh mục kế tiếp từ @INC - giả sử /usr/lib/perl làm ví dụ

    2. Hình thành một thư mục con của thư mục đó bằng cách tham gia hệ thống phân cấp đường dẫn của tên mô-đun (nếu có) và thay thế "::" bằng / hoặc bất kỳ ký tự nào mà hệ điều hành sử dụng làm dấu tách thư mục. Trong hai ví dụ của chúng tôi, mô-đun đầu tiên sẽ được tìm kiếm trong /usr/lib/perl (không có thư mục con) và mô-đun thứ hai trong /usr/lib/perl/This/Here.

    3. LƯU Ý: ở trên là một việc đơn giản hóa nhẹ - @INCmay also contain subroutine references and object references, mà nạp mô-đun như mã tùy chỉnh của họ quy định cụ thể thay vì thực hiện việc tra cứu trong danh bạ theo quy định tại # 2 logic ở trên. Chức năng đó dường như rất hiếm khi được sử dụng và bài viết này giả định rằng toàn bộ @INC chỉ chứa các thư mục.

Hãy cùng điểm qua một ví dụ cụ thể, giả định rằng @INC của bạn có chứa hai thư mục con: ("/usr/lib/perl", "/opt/custom/lib").

Sau đó Perl sẽ tìm kiếm như sau:

 
========================================================================== 
| Module    | Try # | File to try    
========================================================================== 
| MyModule1    | Try 1 | /usr/lib/perl/MyModule1.pm 
| MyModule1    | Try 2 | /opt/custom/lib/MyModule1.pm 
========================================================================== 
| This::Here::MyModule2 | Try 1 | /usr/lib/perl/This/Here/MyModule2.pm 
| This::Here::MyModule2 | Try 2 | /opt/custom/lib/This/Here/MyModule2.pm 
========================================================================== 

Hãy nhớ rằng Perl dịch viên sẽ ngừng cố gắng để tìm kiếm một lần nó tìm thấy các tập tin trong một trong những địa điểm mà không cần cố gắng để xem nếu tập tin là tại các địa điểm sau cũng. Ví dụ. nếu có /usr/lib/perl/This/Here/MyModule2.pm, thì Perl sẽ không tìm kiếm và cũng không quan tâm đến sự tồn tại của /opt/custom/lib/This/Here/MyModule2.pm.

LƯU Ý: @INC được sử dụng bất cứ khi nào thông dịch viên Perl đang sử dụng require cơ chế giống như để nhập mô-đun Perl. Điều này bao gồm:

  • require thị bản thân
  • use MyModule statement (tương đương với yêu cầu + nhập khẩu)
  • use base (tương đương với yêu cầu + "đẩy @ISA")
+2

Nó có thể đáng chú ý, nơi các nội dung của @INC đến từ. Điều này thậm chí có thể là câu trả lời mà OP đang tìm kiếm. Tóm tắt ngắn gọn: Nội dung mặc định chính được tích hợp (chi tiết chính xác của các đường dẫn phụ thuộc vào cài đặt của bạn, rõ ràng). Các cách chính để sửa đổi nó bên ngoài kịch bản của bạn là đặt biến môi trường PERL5LIB (một danh sách đường dẫn được phân cách bằng dấu hai chấm) hoặc cung cấp các tùy chọn '-I/path/to/dir' cho tệp thực thi tại thời gian chạy. (Những chi tiết này cho mảng) – Cascabel

+0

Bất cứ ai cũng có danh sách tốt về chính xác cách @INC được xây dựng? Một trong perlvar perldoc dường như thiếu bất kỳ đề cập nào về PERL5LIB, cũng như cơ chế '$ Config {sitelib}/sitecustomize.pl' (phải được xây dựng trong thời gian biên dịch). – Cascabel

+0

@DVK: Tuyệt vời! Giả sử nhầm bạn đã được thực hiện bởi vì các bình luận cho câu hỏi và thực tế là điều này đã awesomely kỹ lưỡng. – Cascabel

2

Theo perlfunc documentation on use:

sử dụng Mô-đun LI ST

Nhập một số ngữ nghĩa vào gói hiện tại từ mô đun được đặt tên, thường bằng cách đánh dấu một số tên chương trình con hoặc tên biến nhất định vào gói của bạn. Nó chính xác tương đương với

BEGIN { require Module; Module->import(LIST); } 

ngoại trừ Mô-đun đó phải là một vật thể.

Vì vậy require làm việc nặng nhọc, và require documentation cung cấp

Nếu EXPR là một bareword, các yêu cầu giả định một phần mở rộng ".pm" và thay thế "::" với "/" trong tên tập tin cho bạn, để làm cho nó dễ dàng để tải các mô-đun chuẩn. Hình thức tải mô-đun này không làm thay đổi không gian tên của bạn.

Nói cách khác, nếu bạn cố gắng này:

require Foo::Bar; # a splendid bareword 

Các yêu cầu chức năng sẽ thực sự tìm kiếm các "Foo/Bar.pm" tập tin trong các thư mục chỉ định trong mảng @INC.

5

Mặc dù điều này không trực tiếp trả lời câu hỏi, dưới đây là một số kỹ thuật đơn giản để xác định đường dẫn đầy đủ đến tệp mô-đun bạn muốn sử dụng.

Để xem nội dung mặc định của mảng @INC, cùng với rất nhiều thông tin khác, từ dòng lệnh:

perl -V  

Nếu bạn muốn biết vị trí của các module Carp:

perldoc -l Carp 

Bên trong tập lệnh, in nội dung của hàm băm %INC hữu ích để xác định mô-đun thực tế bạn đang sử dụng, đặc biệt nếu bạn đã sửa đổi @INC từ giá trị mặc định:

use Carp; 
print $INC{'Carp.pm'}; 

Tập lệnh đơn giản này cũng có thể được sử dụng để Find installed Perl modules matching a regular expression và để xác định bất kỳ mô-đun trùng lặp nào trong các thư mục khác nhau.

+0

@toolic - câu trả lời này liên quan chặt chẽ đến OP câu hỏi, nhưng tôi cảm thấy nó là phần nào tách biệt với nó (ví dụ như "nơi mà các mô-đun tôi nhập khẩu đến từ"). Bạn có thể đăng tải nó như là một Q + A riêng biệt trên SO (tôi sẽ liên kết với nó), hoặc cho tôi sự đồng ý của bạn để hỏi nó như là một Q riêng biệt và đăng câu trả lời của bạn (hoặc để tôi đăng lại)? – DVK

+0

đã hoàn tất! http://stackoverflow.com/questions/2527990/how-do-i-find-which-file-contains-perl-module-my-script-uses – DVK

+0

@DVK - Nếu tôi có hai phiên bản perl trong đường dẫn cửa sổ của tôi môi trường biến, sau đó làm thế nào để hệ thống biết perl để chọn? Nó là cái đầu tiên? Tôi có các perls khác nhau cho các phần mềm khác nhau được cài đặt trên máy tính của tôi. Chúng được cài đặt cùng với phần mềm. – stack1