warn#
Εκπέμπει μια προειδοποίηση στο STDERR.
Η warn συμβολοσειροποιεί το LIST και τυπώνει το αποτέλεσμα στο STDERR - ο ίδιος μηχανισμός μορφοποίησης με τη die, μείον το ξετύλιγμα. Ο έλεγχος επιστρέφει στον καλούντα· τίποτα δεν εκπέμπεται, τίποτα δεν πιάνεται. Καταφύγετε σε αυτή όταν το πρόγραμμα πρέπει να συνεχίσει να εκτελείται αλλά ο χρήστης, ο διαχειριστής, ή το log αξίζει να ακούσει κάτι αναπάντεχο.
Σύνοψη#
warn LIST
warn $message
warn # re-surface current $@ as a warning
Τι επιστρέφεται#
Η warn επιστρέφει 1 υπό κανονικές συνθήκες. Η τιμή επιστροφής σχεδόν ποτέ δεν είναι χρήσιμη - το νόημα της κλήσης είναι η παρενέργεια στο STDERR (ή σε ό,τι κάνει το $SIG{__WARN__} με το μήνυμα).
Σε αντίθεση με τη die, η warn δεν ξετυλίγει. Η εκτέλεση συνεχίζει με την εντολή μετά την κλήση.
Καθολική κατάσταση που επηρεάζει#
$@- διαβάζεται από τη μορφή χωρίς ορίσματα. Αν το$@κρατά μη κενή τιμή, ηwarnτην επανεμφανίζει (δείτε Διάδοση παρακάτω). Ηwarnδεν γράφει το$@.$,,$\- δεν χρησιμοποιούνται. Ηwarnδεν είναιprint· οι διαχωριστές εξόδου και ο διαχωριστής εγγραφών δεν παίζουν κανέναν ρόλο. Το μήνυμα γράφεται ως μία μόνο συμβολοσειρά.$.- ο τρέχων αριθμός γραμμής εισόδου, προσαρτάται σε μηνύματα που δεν τελειώνουν σε νέα γραμμή.$SIG{__WARN__}- αν είναι ορισμένο, ο χειριστής εκτελείται αντί της εγγραφής στοSTDERR. Δείτε Το hook$SIG{__WARN__}παρακάτω.STDERR- ο προεπιλεγμένος προορισμός. Οποιαδήποτε ανακατεύθυνση τουSTDERR(στο επίπεδο κελύφους με2>,open STDERR, ..., ή στρώμα PerlIO) επηρεάζει το πού προσγειώνεται η έξοδος τηςwarn.
Ο κανόνας τελικής νέας γραμμής#
Ισχύει ο ίδιος κανόνας με τη die, και για τον ίδιο λόγο:
Το μήνυμα τελειώνει σε
"\n"- χρησιμοποιείται αυτούσιο. Τίποτα δεν προσαρτάται. Χρησιμοποιήστε αυτό για προειδοποιήσεις που αποτελούν πλήρη διαγνωστικά για τον χρήστη.Το μήνυμα δεν τελειώνει σε
"\n"- η Perl προσαρτά" at FILE line N", και αν διαβάζεται αρχείο,", <HANDLE> line M", και έπειτα ένα τελικό"."και νέα γραμμή. Χρησιμοποιήστε αυτό όταν ο εντοπισμός του σημείου κλήσης είναι πιο χρήσιμος από ένα ταξινομημένο μήνυμα.
warn "cache is stale\n"; # "cache is stale\n"
warn "cache is stale"; # "cache is stale at main.pl line 42.\n"
Σε προειδοποιήσεις με τιμή αναφοράς δεν προσαρτάται ποτέ πληροφορία τοποθεσίας. Η συμβολοσειροποίηση ενός αντικειμένου για την προσθήκη αρχείου και γραμμής θα ακύρωνε το νόημα της μετάδοσής του.
Διάδοση: warn χωρίς όρισμα (ή με κενή συμβολοσειρά)#
Όταν το LIST είναι κενό ή συμβολοσειροποιείται σε "", η warn δεν εκπέμπει φρέσκο μήνυμα - επανεμφανίζει ό,τι βρίσκεται στο $@:
Αν το
$@είναι μη κενό, ηwarnπροσαρτά"\t...caught"σε αυτό και εκπέμπει το αποτέλεσμα. Αυτός είναι ο κανονικός τρόπος να αντιληφθείτε ότι μια εξαίρεση πιάστηκε χωρίς να την αφήσετε να πεθάνει σιωπηρά:eval { risky() }; warn if $@; # "<whatever died>\n\t...caught at ..."
Αν και το
$@είναι κενό, χρησιμοποιείται η συμβολοσειρά"Warning: Something's wrong".
Αυτό είναι σκόπιμα ασύμμετρο με τη die: η die χωρίς όρισμα ξανα-εκπέμπει (ενεργοποιώντας τον μηχανισμό διάδοσης και το hook PROPAGATE για αντικείμενα)· η warn χωρίς όρισμα αναφέρει ό,τι βρίσκεται ήδη στο $@.
Το hook $SIG{__WARN__}#
Ο ορισμός του $SIG{__WARN__} εγκαθιστά χειριστή που εκτελείται αντί της προεπιλεγμένης εγγραφής στο STDERR. Ο χειριστής λαμβάνει την εξαίρεση που προκύπτει από το LIST ως μοναδικό όρισμα και είναι υπεύθυνος για τη διάθεσή της - καταγραφή, επανεγγραφή, κλιμάκωση σε die, ή απόρριψη στο πάτωμα:
local $SIG{__WARN__} = sub {
my ($msg) = @_;
return if $msg =~ /^Use of uninitialized/; # silently drop
log_warning($msg);
};
Τρεις ασυμμετρίες με το $SIG{__DIE__} αξίζει να εμπεδωθούν:
Το προεπιλεγμένο μήνυμα καταστέλλεται. Το
$SIG{__DIE__}εκτελείται παράλληλα με τον μηχανισμό εξαιρέσεων· το$SIG{__WARN__}εκτελείται αντί της προεπιλεγμένης εγγραφής στοSTDERR. Αν ο χειριστής δεν κάνει τίποτα, η προειδοποίηση απορρίπτεται σιωπηρά.Για να περάσετε διαπεραστικά την προειδοποίηση, καλέστε ξανά
warn. Ο χειριστής δεν εισέρχεται ξανά για τη δική του κλήσηwarn, οπότε δεν υπάρχει άπειρος βρόχος:local $SIG{__WARN__} = sub { log_warning($_[0]); warn $_[0]; # re-emit to STDERR as well };
Ένας χειριστής
__WARN__μπορεί να αποσιωπήσει υποχρεωτικές προειδοποιήσεις - προειδοποιήσεις που τοno warningsδεν μπορεί να απενεργοποιήσει. Αυτό κάνει το$SIG{__WARN__}βαριά σφύρα· προτιμήστεno warnings '<category>'για στοχευμένη καταστολή και κρατήστε τον χειριστή για δρομολόγηση ή κλιμάκωση.
# wipe out *all* compile-time warnings, then switch on at runtime
BEGIN { $SIG{'__WARN__'} = sub { warn $_[0] if $DOWARN } }
my $foo = 10;
my $foo = 20; # duplicate-my silenced
$DOWARN = 1;
warn "\$foo is alive and $foo"; # now shows up
Η ενσωματωμένη warn έναντι του use warnings#
Αυτά είναι διαφορετικά πράγματα. Μη τα μπερδεύετε:
Η
warnείναι ενσωματωμένη συνάρτηση που εκπέμπει ένα μήνυμα τώρα. Την καλείτε εσείς.Το
use warningsείναι pragma που ενεργοποιεί κατηγορίες διαγνωστικών μηνυμάτων κατά τη μεταγλώττιση και κατά τον χρόνο εκτέλεσης (μη αρχικοποιημένες τιμές, παρωχημένα χαρακτηριστικά, μη ανοιγμένα filehandles, και ούτω καθεξής). Ο μεταγλωττιστής και ο διερμηνέας εκπέμπουν αυτά τα διαγνωστικά εκ μέρους σας, χρησιμοποιώντας τον ίδιο μηχανισμό που χρησιμοποιεί ηwarn.
Τα διαγνωστικά της pragma ρέουν μέσα από το $SIG{__WARN__} ακριβώς όπως οι ρητές κλήσεις warn. Το no warnings '<category>' καταστέλλει τα διαγνωστικά της pragma στη λεξιλογική εμβέλειά του αλλά δεν έχει επίδραση σε ρητή warn που γράψατε εσείς - αυτή η κλήση πάντα πυροδοτείται.
Παραδείγματα#
Αναφορά ανακτήσιμου προβλήματος και συνέχιση της εκτέλεσης:
open my $fh, "<", $path
or warn "skipping $path: $!\n" and next;
Διαγνωστικό λειτουργίας ανάπτυξης με προσαρτημένη τοποθεσία:
warn "unexpected record shape";
# unexpected record shape at parser.pl line 87.
Παρατήρηση μιας εξαίρεσης που πιάστηκε χωρίς να κατασταλεί:
eval { load_config() };
warn if $@; # surfaces "...caught at ..."
Δρομολόγηση κάθε προειδοποίησης μέσω ενός logger, με εκτύπωση και στο STDERR:
local $SIG{__WARN__} = sub {
my ($msg) = @_;
$logger->warn($msg);
print STDERR $msg; # preserve default visibility
};
Κλιμάκωση συγκεκριμένης προειδοποίησης σε μοιραίο σφάλμα:
local $SIG{__WARN__} = sub {
die @_ if $_[0] =~ /corrupt database/;
warn @_; # everything else: default path
};
Μετάδοση blessed αντικειμένου για δομημένες προειδοποιήσεις (ο παραλήπτης ενός hook $SIG{__WARN__} λαμβάνει την αναφορά, όχι συμβολοσειροποιημένη μορφή):
local $SIG{__WARN__} = sub {
my ($w) = @_;
if (ref($w) && $w->isa('MyApp::Warning')) {
$logger->record($w);
}
else {
print STDERR $w;
}
};
warn MyApp::Warning->new(code => 'SLOW_IO', detail => $path);
Οριακές περιπτώσεις#
Λίστα με δύο ή περισσότερα στοιχεία συμβολοσειροποιείται και συνενώνεται:
warn "bad record ", $n, ": ", $raw. Ο κανόνας νέας γραμμής εφαρμόζεται στο συνενωμένο αποτέλεσμα.Κενή λίστα (
warn;ήwarn "";) ενεργοποιεί τη διαδρομή διάδοσης, όχι φρέσκο μήνυμα.Προειδοποίηση με τιμή αναφοράς μέσα σε χειριστή
$SIG{__WARN__}: ο χειριστής λαμβάνει την αναφορά αμετάβλητη. Αν δεν είναι εγκατεστημένος χειριστής, η αναφορά συμβολοσειροποιείται στοSTDERRμέσω της υπερφόρτωσης""(ή της προεπιλογής της PerlMyClass=HASH(0x...)).warnμέσα σε$SIG{__WARN__}: δεν εισέρχεται ξανά στον χειριστή. Η κλήση γράφει στοSTDERRσαν να μην ήταν εγκατεστημένος χειριστής. Αυτό κάνει ασφαλή τον ιδιωματισμό «pass through».warnκατά την καθολική καταστροφή: εξακολουθεί να λειτουργεί, αλλά τοSTDERRμπορεί ήδη να είναι κλειστό σε παθολογικές περιπτώσεις. Προειδοποιήσεις από χειριστέςDESTROYπου εκτελούνται κατά την έξοδο του διερμηνέα μπορεί να εξαφανιστούν.STDERRκλειστό ή ανακατευθυνόμενο: ηwarnγράφει σε ό,τι δείχνει αυτή τη στιγμή τοSTDERR. Αν τοSTDERRείναι κλειστό, η εγγραφή αποτυγχάνει σιωπηρά· δεν εγείρεται σφάλμα, επειδή η ίδια ηwarnδεν ελέγχει.Καμία σχέση με τα
$\/$,: η προσθήκηlocal $\ = "\n"δεν κάνει τοwarn "x"να τυπώσει νέα γραμμή. Ο κανόνας τελικής νέας γραμμής είναι ο μόνος μηχανισμός προσθήκης νέας γραμμής για τηνwarn.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
die- ίδιοι κανόνες μορφοποίησης (η τελική νέα γραμμή καταστέλλει την τοποθεσία, οι αναφορές περνούν αμετάβλητες), αλλά εγείρει εξαίρεση αντί να αναφέρει και να συνεχίσειeval- συνδυάζεται με τη μορφή χωρίς ορίσματα τηςwarnγια τον ιδιωματισμό «πιάσε, εξέτασε, επανεμφάνισε»$@- η πηγή από την οποία αναφέρει ηwarnχωρίς όρισμα$SIG{__WARN__}- το hook που αντικαθιστά την προεπιλεγμένη εγγραφή στοSTDERR· χρησιμοποιήστε το για δρομολόγηση, φιλτράρισμα, ή κλιμάκωσηCarp-carp,cluck,croak,confess: προειδοποιήσεις και εξαιρέσεις που αναφέρουν από την οπτική του καλούντος και όχι του σημείου κλήσης, που είναι σχεδόν πάντα αυτό που θέλει μια βιβλιοθήκη