2010-05-19 28 views
14

tôi đang học Perl, và trong rất nhiều những ví dụ tôi thấy lỗi được xử lý như thế nàyCác phương pháp hay nhất để xử lý lỗi trong Perl là gì?

open FILE, "file.txt" or die $!; 

die ở giữa một kịch bản thực sự là cách tốt nhất để đối phó với một lỗi?

+6

Đối với các cuộc thảo luận về ngoại lệ perl, hãy xem [Điều gì bị hỏng về ngoại lệ trong perl?] (Http://stackoverflow.com/questions/2165161/whats-broken-about-exceptions-in-perl), [Bạn có sử dụng lớp ngoại lệ trong các chương trình Perl của bạn? Tại sao hoặc tại sao không?] (Http://stackoverflow.com/questions/2439966/do-you-use-an-exception-class-in-your-perl-programs-why-or-why-not) và [ Xử lý ngoại lệ hướng đối tượng trong Perl - có đáng không?] (Http://stackoverflow.com/questions/503189/object-oriented-exception-handling-in-perl-is-it-worth-it) – Ether

Trả lời

21

Cho dù die là thích hợp ở giữa tập lệnh thực sự phụ thuộc vào những gì bạn đang làm. Nếu nó chỉ có hàng chục dòng, thì tốt thôi. Một công cụ nhỏ với vài trăm dòng, sau đó xem xét thú nhận (xem bên dưới). Nếu đó là một hệ thống hướng đối tượng lớn với nhiều lớp và mã được kết nối với nhau, thì có thể một đối tượng ngoại lệ sẽ tốt hơn.

thú nhận trong gói Carp:
Thường thì lỗi dẫn đến chết không nằm trên đường chết báo cáo. Thay thế chết bằng thú nhận (xem Gói cá chép) sẽ cung cấp dấu vết ngăn xếp (cách chúng tôi truy cập vào dòng này) hỗ trợ rất nhiều trong việc gỡ lỗi.

Để xử lý ngoại lệ từ nội trang Perl, tôi thích sử dụng autodie. Nó bắt lỗi từ open và các cuộc gọi hệ thống khác và sẽ ném ngoại lệ cho bạn mà không phải thực hiện bit or die. Các trường hợp ngoại lệ này có thể bị bắt với số eval { } hoặc tốt hơn, bằng cách sử dụng Try::Tiny.

+4

+1 để đề xuất 'autodie'. –

+1

Tôi luôn nghĩ rằng họ nên gọi nó là 'autoOrDie' :) – friedo

+0

@friedo Nó sẽ trông giống như' authorDie' :) – dolmen

3

Cách tiếp cận hiện đại hơn là sử dụng thư viện chuẩn Carp.

use Carp; 
my $fh; 
open $fh, '<', "file.txt" or confess($!); 

Ưu điểm chính là nó cho dấu vết ngăn xếp trên mạng.

+0

Vâng , croak không cung cấp dấu vết ngăn xếp trừ khi bạn đặt một số thứ khác trên Cá chép. –

+0

@brian: rên rỉ, cố định. –

+1

Cảm ơn! Tôi không biết về Carps .... nhưng kể từ khi nào Carps croak? – SystematicFrank

0

tôi sử dụng chết nhưng tôi quấn nó trong khối eval để kiểm soát việc xử lý lỗi:

my $status = eval 
{ 
    # Some code... 
}; 

Nếu 'eval' thất bại:

  1. $status sẽ không xác định.
  2. [email protected] sẽ được thiết lập để bất cứ điều gì thông báo lỗi được sản xuất (hoặc nội dung của một die)

Nếu 'eval' thành công:

  1. $status sẽ là giá trị trả về cuối cùng của khối.
  2. [email protected] sẽ được đặt thành ''.
+5

Có rất nhiều vấn đề với 'eval {}' cần phải làm việc xung quanh. Sử dụng Try :: Tiny để thay thế. Nó kết thúc tốt đẹp tất cả các boilerplate độc ​​hại trong một gói sạch sẽ, dễ sử dụng. – daotoad

+1

Có rất nhiều vấn đề với 'eval {}' cần phải làm việc xung quanh ... nếu bạn quan tâm đến việc xác định lỗi. Nếu bạn định thực hiện cùng một hành động bất chấp nguyên nhân của nó, một khối đơn giản 'eval' hoạt động tốt. Nhưng, vâng: Sử dụng 'Try :: Tiny' trong tất cả các trường hợp khác. –

+0

Tôi sẽ thử điều đó trong lần sau tôi viết một số Perl. Tôi sử dụng cách này để giả mạo một thử-catch (bằng cách thêm một kiểm tra của $ @ sau khi khối eval.) Cảm ơn lời khuyên. –

12

Vì tôi sử dụng Log::Log4perl hầu như ở mọi nơi, tôi sử dụng $logger->logdie thay vì die. Và nếu bạn muốn kiểm soát nhiều hơn ngoại lệ của mình, hãy xem xét Exception::Class.

Tốt hơn là nên xem ngoại lệ của bạn với Try::Tiny (xem tài liệu tại sao).

6

Trừ khi bạn có ý tưởng cụ thể hơn, thì bạn muốn chết khi những điều bất ngờ xảy ra.

  • Dying tại sự thất bại để mở một tập tin và đưa ra các tên tập tin là tốt hơn so với các hệ thống nói với bạn nó không thể đọc từ hay ghi vào một không xác định vô danh.

  • Nếu bạn đang nói về "tập lệnh", nói chung bạn đang nói về một đoạn mã khá đơn giản. Không phải các lớp cần phối hợp (không thường). Trong một mô-đun Perl , có một ý tưởng giả là bạn không sở hữu môi trường thực thi, do đó, hoặc phần mềm chính quan tâm và nó bắt mọi thứ trong một eval, HOẶC nó không thực sự quan tâm và chết sẽ là tốt. Tuy nhiên, một trong những bạn nên thử một chút mạnh mẽ hơn như là một mô-đun và chỉ cần trả lại undefs hoặc một cái gì đó.

  • Bạn có thể bắt bất cứ điều gì chết (hoặc croaks) trong một khối eval. Và bạn có thể xử lý cụ thể hơn ở đó.

  • Nhưng nếu bạn muốn kiểm tra $! sau đó viết mã đó và bạn sẽ có độ phân giải cụ thể hơn.

  • Hãy xem tiêu chuẩn gần như phổ quát của việc sử dụng strict. Đó là mã chết trên cú pháp có vấn đề, thay vì cho phép bạn tiếp tục.

Vì vậy, tôi nghĩ rằng ý tưởng chung là: có, DIE trừ khi bạn có một ý tưởng tốt hơn về cách điều cần được xử lý. Nếu bạn đặt đủ tầm nhìn xa vào nó, bạn có thể được tha thứ cho một hoặc hai lần bạn không chết, bởi vì bạn biết bạn không cần.

Các vấn đề liên quan