2009-04-08 6 views
40

Gần đây tôi đã viết một kịch bản Perl mới để giết các quy trình dựa trên tên hoặc tên người dùng và mở rộng nó bằng cách sử dụng Lớp để tôi có thể sử dụng lại mã quy trình trong các chương trình khác. Bố cục hiện tại của tôi là -Kịch bản Perl của tôi có thể tìm thấy mô-đun của nó trong cùng một thư mục như thế nào?

/home/mutew/src/prod/pskill  <-- Perl script 
/home/mutew/src/prod/Process.pm <-- Package to handle process descriptions 

Tôi đã thêm ~/src/prod vào biến $ PATH để truy cập tập lệnh từ bất kỳ đâu. Khi chạy tập lệnh từ bất kỳ thư mục nào khác ngoài thư mục thường trú của nó dẫn đến "Không thể định vị Process.pm trong @INC" (điều này có thể hiểu được ngoài các thư mục được chia sẻ trong/usr, @INC chỉ bao gồm thư mục hiện tại - '.'). Một giải pháp mà tôi đã sử dụng là chỉ thị lib sử dụng như vậy -

use lib '/home/mutew/src/prod'; 

nhưng đây là vấn đề về tính di động chính. Bất kỳ giải pháp nào cũng sẽ cho phép tôi xuất tập lệnh sang các hệ thống khác mà không có và thay đổi?


EDIT

  1. tôi đã chọn câu trả lời 'depesz' là đúng vì sự đơn giản và cốt lõi sử dụng mô-đun của nó.
  2. câu trả lời của brian d foy mặc dù đề xuất các phương pháp khác để thực hiện tương tự (TMTOWTDI), đóng góp của mình trong perlfaq8 khiến câu hỏi này hoàn toàn thừa.
+0

có thể chỉ là cài đặt của tôi, nhưng nếu cả hai tệp đều nằm trong cùng một thư mục, tôi chỉ đơn giản là "sử dụng FILENAME.pm". Sau đó, "my $ newVar = PACKAGENAME-> new();" cho bất kỳ lập trình đối tượng nào. –

+0

Wow điều này sẽ dễ dàng hơn rất nhiều trong perl hơn thế này! Làm cho những điều dễ dàng dễ dàng, vv .. –

Trả lời

42

Cách tiếp cận đơn giản nhất tôi thấy nó sử dụng mô-đun FindBin. Như thế này:

use FindBin; 
use lib $FindBin::Bin; 

Nói chung tôi thích để có kịch bản của tôi được cung cấp trong một cách mà chương trình này trong bất cứ điều gì/bin, và thư viện là trong bất cứ điều gì/lib

Trong những tình huống này tôi sử dụng một chút phức tạp hơn cách tiếp cận:

use Cwd qw(abs_path); 
use FindBin; 
use lib abs_path("$FindBin::Bin/../lib"); 

Cuộc gọi abs_path là để làm cho @INC chứa bất kỳ điều gì/lib và chỉ là một thay đổi nhỏ, nhưng làm cho việc đọc thông báo lỗi trở nên dễ dàng hơn.

+3

Đừng quên rằng abs_path trả về kết quả bị nhiễm độc ở chế độ taint. Bạn phải sử dụng 'sử dụng lib (abs_path (" $ FindBin :: Bin/../ lib ") = ~ m {^ (/.*)}) [0];' hoặc chỉ sử dụng 'sử dụng lib" $ FindBin :: Bin /../ lib ";' beacuse không có lý do để canonize đường dẫn. –

3

Hãy xem Par::Packer. Nó tạo ra một tệp thực thi với tất cả các phụ thuộc của tập lệnh được bao gồm. Nó làm cho việc phân phối trở nên dễ dàng. Bạn cũng có thể cung cấp cho người dùng phiên bản của mô-đun có thể được cài đặt trên hệ thống của họ. Xem Module::Starter để có cách dễ dàng để xây dựng tất cả các tệp cần thiết để tạo phân phối theo kiểu CPAN chuẩn.

9

Từ perlfaq8, trả lời "How do I add a directory to my include path (@INC) at runtime?". Có một số câu trả lời khác cho các câu hỏi xung quanh vấn đề này.


Làm cách nào để thêm thư mục vào đường dẫn bao gồm của tôi (@INC) khi chạy?

Dưới đây là những cách đề nghị để sửa đổi bao gồm bạn con đường, bao gồm các biến môi trường, công tắc thời gian chạy, và trong mã lệnh:

môi trường PERLLIB biến

$ export PERLLIB=/path/to/my/dir 
$ perl program.pl 

môi trường PERL5LIB biến

$ export PERL5LIB=/path/to/my/dir 
$ perl program.pl 

cờ dòng lệnh perl -Idir

$ perl -I/path/to/my/dir program.pl 

các pragma sử dụng lib:

use lib "$ENV{HOME}/myown_perllib"; 

cuối cùng là đặc biệt hữu ích bởi vì nó biết về kiến ​​trúc phụ thuộc máy. Các mô-đun thực dụng lib.pm lần đầu tiên được bao gồm trong phiên bản 5.002 của Perl.

+0

Tôi đọc perlfaq8 sau cùng ngày và tìm thấy câu trả lời tôi cần trong bài viết đóng góp của bạn. Tôi tự hỏi tại sao bạn đã bao gồm phương pháp thứ hai (sử dụng Cwd) mặc dù kể từ khi @INC đã có một mục nhập cho thư mục hiện tại - '.' – aks

0

Để chuyển đổi các liên kết tương đối thành tuyệt đối và thêm vào @INC, tôi thường sử dụng ex :: lib. Tất nhiên, điều này chỉ hữu ích nếu bạn định giữ các vị trí tương đối của tập lệnh và mô-đun giống nhau trên tất cả các máy mà bạn định chạy tập lệnh của mình.

38

Tôi tò mò tại sao các giải pháp đơn giản

use File::Basename; 
use lib dirname (__FILE__); 
use SomeModuleLocatedInTheSameDirectoryAsThisPerlScriptOrModule; 

không đi lên. Mô-đun FindBin dường như có một số vấn đề nếu tệp không phải là tập lệnh perl thực thi chính, nhưng chỉ đơn giản là một mô-đun Perl không thực thi được. Ít nhất đó là cách tôi giải thích nhận xét trong số documentation. Đã không thực sự kiểm tra nó.

Để có bất cứ con đường khác liên quan đến vị trí của tập tin Perl này, làm cái gì đó như

use File::Basename; 
use lib dirname (__FILE__) . "/MyModules"; 
+3

Tôi thích cách tiếp cận này rất nhiều - tôi chỉ phải sử dụng 'sử dụng Cwd qw (abs_path); sử dụng lib dirname (abs_path (__ FILE __)); 'để làm cho kịch bản có thể gọi được thông qua một liên kết tượng trưng. Chúc mừng! – sdaau

+0

Đây là câu trả lời duy nhất ở đây làm việc –

+0

tuyệt vời! Những công việc này! –

-1

FindBin::libs sẽ tìm thấy tất cả các libs của bạn được đặt ở những nơi hợp lý liên quan đến các đường đi từ nơi kịch bản của bạn đang chạy.

-1

Chỉ cần giữ cho nó đơn giản. Không cần nhập bất kỳ thư viện nào; chỉ cần tìm ra thư mục làm việc hiện tại của bạn:

use lib "$ENV{PWD}/relativ_path_own_perllib"; 

Đối với vấn đề tương tự, bạn có thể đọc ra các biến môi trường mà cung cấp thông tin của bạn về bạn đang ở đâu, thư mục home của bạn, công cụ hệ điều hành, và như vậy, chỉ với một hàng mã lập trình trong shell-terminal, như:

perl -e 'map { print; print " : ". $ENV{$_}." \n\r"; } sort keys %ENV ' 

Không cần phải ràng buộc một số thư viện; chỉ cần sử dụng %ENV-Hash.

+0

'$ ENV {PWD}' không giải quyết được vấn đề - trái lại. Nó trả về thư mục làm việc của _user, chứ không phải vị trí của tập lệnh. – pipe

0

Bạn có thể tạo diện mạo perl trong bất kỳ thư mục nào bằng cách sử dụng cờ -I. Ở đây, -I là viết tắt của @INC là mảng đường dẫn trong đó perl tìm kiếm các mô-đun. Sử dụng -I thêm đường dẫn đã cho vào mảng @INC cho việc thực thi này.

ví dụ:

perl -I lib bin/script.pl 

nơi lib chứa các module Tôi muốn sử dụng.

Tôi biết rằng tính năng này hoạt động cho perl 5. Tôi không chắc chắn về các phiên bản khác.