Αρθρώματα

require#

Φορτώνει ένα αρχείο πηγαίου κώδικα Perl σε χρόνο εκτέλεσης, ή απαιτεί μια ελάχιστη έκδοση Perl.

Η require έχει τρεις μορφές που κάνουν αρκετά διαφορετικά πράγματα. Με αριθμό έκδοσης επιβεβαιώνει ότι ο τρέχων διερμηνέας είναι αρκετά νέος. Με bareword φορτώνει ένα άρθρωμα μετατρέποντας το Foo::Bar σε Foo/Bar.pm και αναζητώντας στο @INC. Με συμβολοσειρά κατά τον χρόνο εκτέλεσης ή με $_ φορτώνει ένα όνομα αρχείου ως έχει. Και οι τρεις είναι λειτουργίες χρόνου εκτέλεσης - αντίθετα με την use, που είναι require + import τυλιγμένα σε ένα μπλοκ BEGIN κατά τη μεταγλώττιση.

Σύνοψη#

require VERSION
require EXPR
require

Τι επιστρέφεται#

Για τη μορφή ελέγχου έκδοσης: 1 αν η τρέχουσα Perl είναι αρκετά νέα· διαφορετικά εκτοξεύεται εξαίρεση (Perl vX.Y.Z required--this is only ...). Δεν υπάρχει τίποτα προς έλεγχο.

Για τις μορφές φόρτωσης αρχείων: η αληθής τιμή που επιστρέφει η τελευταία δήλωση του φορτωμένου αρχείου, ή 1 αν το αρχείο ενεργοποιεί το χαρακτηριστικό module_true (προεπιλεγμένο υπό use v5.38 και μεταγενέστερα). Μια δεύτερη require της ίδιας διαδρομής επιστρέφει 1 χωρίς να επανεκτελέσει το αρχείο. Η αποτυχία εκτοξεύει εξαίρεση - είτε το σφάλμα μεταγλώττισης/χρόνου εκτέλεσης από το αρχείο, Can't locate Foo/Bar.pm in @INC ..., ή Foo/Bar.pm did not return true value.

Τυλίξτε σε eval όταν θέλετε να ελέγξετε αν ένα άρθρωμα είναι φορτώσιμο:

eval { require Some::Optional::Module };
if ($@) { ... }                    # module missing or broken

Καθολική κατάσταση που επηρεάζει#

  • @INC - η διαδρομή αναζήτησης για τις μορφές bareword και σχετικού ονόματος αρχείου. Οι εγγραφές μπορεί να είναι συμβολοσειρές καταλόγων, coderefs, αναφορές πινάκων, ή blessed αντικείμενα (δείτε Γάντζοι @INC παρακάτω).

  • %INC - αντιστοιχίζει το ζητούμενο όνομα αρχείου (Foo/Bar.pm) στην απόλυτη διαδρομή που φορτώθηκε. Η require τη συμβουλεύεται για να αποφύγει διπλή φόρτωση και τη θέτει σε επιτυχία. Εγγραφή με τιμή undef σημαδεύει αρχείο του οποίου η μεταγλώττιση απέτυχε.

  • $_ - χρησιμοποιείται ως όνομα αρχείου όταν η require καλείται χωρίς όρισμα.

  • ${^HOOK}{require__before} και ${^HOOK}{require__after} - προαιρετικά coderefs που εκτελούνται γύρω από κάθε require, διαθέσιμα για περιτυλίγματα ιχνηλασίας και οργανολογίας.

Οι τρεις μορφές#

require VERSION - έλεγχος ελάχιστης Perl#

Το VERSION είναι είτε v-string όπως v5.38.0 (συγκρίνεται έναντι της $^V) ή αριθμητικό κυριολεκτικό όπως 5.038000 (συγκρίνεται έναντι της $]). Αν ο τρέχων διερμηνέας είναι παλαιότερος, η require εκτοξεύει εξαίρεση.

require v5.38;        # preferred
require 5.038;        # numeric; same effect
require 5.038_000;    # same; pre-5.6 syntax

Αυτός είναι έλεγχος χρόνου εκτέλεσης. Αν θέλετε ο έλεγχος να γίνει κατά τη μεταγλώττιση (ώστε το σενάριο να μην εκκινεί ποτέ σε παλιά Perl), χρησιμοποιήστε αντί αυτής use VERSION:

use v5.38;            # compile-time equivalent

require EXPR όπου το EXPR είναι bareword - άρθρωμα κατ” όνομα#

Ένα bareword ερμηνεύεται ως όνομα αρθρώματος. Η require αντικαθιστά κάθε :: με / και προσαρτά .pm, και στη συνέχεια αναζητά στο @INC:

require Foo::Bar;     # looks for Foo/Bar.pm in @INC

Αυτή η μορφή επίσης αυτο-δημιουργεί τη stash κατά τη μεταγλώττιση - το hash πακέτου Foo::Bar:: εμφανίζεται ακόμη και αν η φόρτωση αποτύχει μετέπειτα. Δεν εισάγονται σύμβολα· η require μόνο φορτώνει κώδικα.

Πριν δοκιμάσει το Foo/Bar.pm, η require ψάχνει για το Foo/Bar.pmc στον ίδιο κατάλογο και το προτιμά αν το βρει. Ο γάντζος .pmc επιτρέπει σε εργαλεία build να αποστέλλουν προμεταγλωττισμένα συνοδευτικά αρχεία δίπλα στις πηγές.

require EXPR όπου το EXPR είναι συμβολοσειρά - αρχείο κατά διαδρομή#

Οποιαδήποτε έκφραση που δεν είναι bareword αντιμετωπίζεται ως κυριολεκτικό όνομα αρχείου. Καμία μετατροπή ::, καμία προσάρτηση .pm, καμία αυτο-δημιουργία stash:

require "Foo/Bar.pm";           # explicit .pm path
require "$config_dir/init.pl";  # arbitrary filename

my $class = 'Foo::Bar';
require $class;                 # ERROR: looks for file "Foo::Bar"

Η τελευταία γραμμή είναι η κλασική παγίδα: μόλις το όνομα του αρθρώματος βρίσκεται σε βαθμωτό, είναι συμβολοσειρά, όχι bareword. Για να φορτώσετε άρθρωμα του οποίου το όνομα υπολογίζεται, είτε κάντε τη μετατροπή εσείς, είτε περάστε από eval:

(my $file = "$class.pm") =~ s{::}{/}g;
require $file;

eval "require $class; 1" or die $@;

Αν το EXPR παραλειφθεί εντελώς, χρησιμοποιείται η $_.

Η προστασία του %INC - τα φορτωμένα αρχεία παραμένουν φορτωμένα#

Πριν αναζητήσει στο @INC, η require συμβουλεύεται το %INC. Αν το ζητούμενο όνομα αρχείου είναι παρόν και έχει αληθή τιμή, η require επιστρέφει αμέσως 1 χωρίς να ξαναδιαβάσει το αρχείο. Αν η τιμή είναι undef, μια προηγούμενη φόρτωση απέτυχε και η require εκτοξεύει Compilation failed in require - η Perl αρνείται να ξαναδοκιμάσει ένα αρχείο που έχει ήδη εκραγεί μία φορά σε αυτόν τον διερμηνέα.

Αυτό σημαίνει ότι ο κώδικας ανώτατου επιπέδου ενός αρθρώματος εκτελείται ακριβώς μία φορά ανά διερμηνέα, ανεξάρτητα από το από πόσα μέρη γίνεται require. Η αρχικοποίηση στο σώμα του αρχείου του αρθρώματος είναι μονή λειτουργία· μη βασίζεστε στο ότι θα τρέχει για κάθε κλήση require σε κάθε καλούντα.

Ένας γάντζος είναι ελεύθερος να θέσει ο ίδιος το %INC· αν δεν το κάνει, η require καταγράφει τον γάντζο ως «πηγή» της φόρτωσης.

Η σύμβαση του 1;#

Ιστορικά, κάθε φορτώσιμο αρχείο έπρεπε να επιστρέφει αληθή τιμή ως τελευταία του έκφραση, διαφορετικά η require εκτόξευε filename did not return true value. Ο καθιερωμένος τρόπος για να το εγγυηθεί κανείς είναι ένα τελικό 1;:

package My::Thing;
# ... module code ...
1;                                 # mandatory, pre-5.38

Από την Perl 5.38, το χαρακτηριστικό module_true - προεπιλεγμένα ενεργοποιημένο υπό use v5.38 ή μεταγενέστερα - κάνει κάθε αρχείο που γίνεται require να επιστρέφει σιωπηρά αληθές σε επιτυχημένη μεταγλώττιση. Τα αρχεία που το ενεργοποιούν δεν χρειάζονται πλέον 1;. Όσα όχι, εξακολουθούν να το χρειάζονται.

Αυτό επηρεάζει μόνο τη μονάδα μεταγλώττισης που ενεργοποίησε το χαρακτηριστικό· παλαιά αρθρώματα που φορτώνονται από σύγχρονο καλούντα εξακολουθούν να χρειάζονται το δικό τους 1;.

Όταν το φορτωμένο αρχείο επιστρέφει τιμή και το module_true είναι ανενεργό, αυτή η τιμή είναι αυτό που επιστρέφει η require - αλλά μόνο στην πρώτη φόρτωση. Επόμενες κλήσεις require του ίδιου αρχείου επιστρέφουν 1 από την προσωρινή μνήμη του %INC. Για να αποτυπώσετε αξιόπιστα την τιμή επιστροφής ενός αρχείου, χρησιμοποιήστε do:

my $config = do "config.pl"
    or die "config.pl: ", $@ || $!;

Γάντζοι @INC - coderefs, αναφορές πινάκων, και αντικείμενα#

Οι εγγραφές στο @INC δεν χρειάζεται να είναι συμβολοσειρές καταλόγων. Μια αναφορά αποθηκευμένη στο @INC καλείται γάντζος και έχει την ευκαιρία να ικανοποιήσει την require.

Αναφορά υπορουτίνας#

Καλείται με δύο ορίσματα: το ίδιο το coderef και το όνομα αρχείου (Foo/Bar.pm). Πρέπει να επιστρέφει είτε τίποτα (που σημαίνει «δεν μπορώ να το χειριστώ αυτό· δοκίμασε την επόμενη εγγραφή») είτε μέχρι τέσσερις τιμές:

  1. Μια βαθμωτή αναφορά σε κείμενο πηγαίου κώδικα που προτάσσεται στο αρχείο.

  2. Ένα filehandle από το οποίο διαβάζεται ο υπόλοιπος πηγαίος κώδικας.

  3. Μια υπορουτίνα γεννήτορα ή φίλτρου (δείτε το perldoc perlfunc για το ακριβές πρωτόκολλο).

  4. Προαιρετική κατάσταση που μεταβιβάζεται πίσω στον γεννήτορα.

push @INC, sub {
    my ($self, $filename) = @_;
    return unless $filename eq 'Virtual/Module.pm';
    open my $fh, '<', \"package Virtual::Module; 1;";
    return $fh;
};

Αναφορά πίνακα#

Το πρώτο στοιχείο είναι coderef ή αντικείμενο όπως παραπάνω· το υπόλοιπο είναι κατάσταση που ο γάντζος μπορεί να διαβάζει σε κάθε κλήση. Όταν το πρώτο στοιχείο είναι αντικείμενο με μέθοδο INC ή INCDIR, η μέθοδος λαμβάνει την αναφορά πίνακα ως τρίτο της όρισμα.

push @INC, [\&my_loader, $db_handle, $cache];

Blessed αντικείμενο#

Αν το αντικείμενο έχει μέθοδο INC ή INCDIR, η require καλεί αυτή τη μέθοδο· διαφορετικά, αν το αντικείμενο είναι επίσης coderef, καλείται σαν απλή αναφορά υπορουτίνας. Οι μέθοδοι INC πρέπει να δηλώνονται με το πλήρως κατονομασμένο όνομά τους (sub Foo::INC { ... }), διότι το ακατονόμαστο σύμβολο INC είναι σταθερά συνδεδεμένο με το πακέτο main.

Ένας γάντζος είναι ελεύθερος να ενημερώσει το %INC ώστε να καταγράψει τη διαδρομή που παρείχε· αν δεν το κάνει, η require αποθηκεύει την ίδια την αναφορά του γάντζου.

require έναντι use#

use Foo::Bar qw(x y);

# is almost exactly:

BEGIN {
    require Foo::Bar;
    Foo::Bar->import(qw(x y));
}

Πτυχή

use

require

Πότε εκτελείται

Χρόνος μεταγλώττισης (μέσα σε BEGIN)

Χρόνος εκτέλεσης

Καλεί την import

Ναι

Όχι

Bareword ::/

Ναι

Ναι, όταν καλείται με bareword

Μορφή ελέγχου έκδοσης

use v5.38

require v5.38

Κατάλληλη για

Σταθερές εξαρτήσεις

Προαιρετικά / αργά συνδεόμενα αρθρώματα

Καταφύγετε στην require όταν το άρθρωμα είναι προαιρετικό, φορτώνεται από όνομα που υπολογίζεται, ή φορτώνεται μόνο μέσα σε διακλάδωση που ίσως δεν εκτελεστεί ποτέ. Καταφύγετε στην use για όλα τα υπόλοιπα.

Παραδείγματα#

Ελάχιστη έκδοση Perl σε χρόνο εκτέλεσης:

require v5.38;

Φόρτωση αρθρώματος με bareword - αναζητά στο @INC, αυτο-δημιουργεί το Data::Dumper:: κατά τη μεταγλώττιση:

require Data::Dumper;
Data::Dumper->import;
print Data::Dumper::Dumper(\%ENV);

Προαιρετικό άρθρωμα - υποχωρήστε χαριτωμένα όταν λείπει:

my $have_json = eval { require JSON::PP; 1 };
if ($have_json) {
    print JSON::PP->new->encode($data);
}

Φόρτωση αρθρώματος του οποίου το όνομα υπολογίζεται σε χρόνο εκτέλεσης. Μετατρέψτε σε διαδρομή ονόματος αρχείου· το require $class θα έψαχνε για ένα κυριολεκτικό αρχείο με όνομα Foo::Bar:

my $driver = $ENV{DB_DRIVER} // 'SQLite';
my $class  = "DBD::$driver";
(my $file  = "$class.pm") =~ s{::}{/}g;
require $file;

Φόρτωση αποσπάσματος ρυθμίσεων κατά διαδρομή, διατηρώντας την τιμή επιστροφής του - σημειώστε την do, όχι την require, διότι θέλουμε την τιμή σε κάθε κλήση:

my $config = do '/etc/myapp/config.pl'
    or die "config load failed: ", $@ || $!;

Εγκατάσταση γάντζου @INC που εξυπηρετεί ένα μεμονωμένο εικονικό άρθρωμα από συμβολοσειρά στη μνήμη:

unshift @INC, sub {
    my ($self, $filename) = @_;
    return unless $filename eq 'MyApp/Version.pm';
    my $src = "package MyApp::Version; our \$VERSION = '1.23'; 1;";
    open my $fh, '<', \$src;
    $INC{$filename} = '(generated)';
    return $fh;
};
require MyApp::Version;

Οριακές περιπτώσεις#

  • Bareword έναντι συμβολοσειράς: τα require Foo::Bar και require "Foo::Bar" δεν είναι το ίδιο. Η μορφή bareword μετατρέπεται σε Foo/Bar.pm· η μορφή συμβολοσειράς αναζητά αρχείο με κυριολεκτικό όνομα Foo::Bar.

  • Υπολογιζόμενα ονόματα κλάσεων: το require $class όπου η $class κρατά 'Foo::Bar' αναζητά αρχείο με όνομα Foo::Bar, όχι Foo/Bar.pm. Κάντε εσείς τη μετατροπή του ονόματος, ή χρησιμοποιήστε eval "require $class" όταν το όνομα είναι έμπιστο.

  • Χωρίς όρισμα: η require; χρησιμοποιεί την $_ ως όνομα αρχείου. Σπάνιο σε σύγχρονο κώδικα· σχεδόν πάντα ατύχημα.

  • Οι επανεκτελέσεις δεύτερης ευκαιρίας δεν λειτουργούν: Αν μια require αποτύχει στη μέση της μεταγλώττισης, το %INC καταγράφει undef για αυτό το όνομα αρχείου. Μια μεταγενέστερη require του ίδιου ονόματος βλέπει το undef και εκτοξεύει Compilation failed in require χωρίς να ξανατρέξει το αρχείο. Διαγράψτε την εγγραφή του %INC αν θέλετε πραγματικά να ξαναδοκιμάσετε (αυτό είναι αιχμηρό άκρο· προτιμήστε να διορθώσετε την υποκείμενη αποτυχία).

  • Αφαίρεση του σχετικού .: το . αφαιρέθηκε από το προεπιλεγμένο @INC στην Perl 5.26. Ένα σενάριο που παλιά έβρισκε το Foo/Bar.pm δίπλα του πρέπει τώρα να προσθέτει ρητά τον δικό του κατάλογο (use FindBin; use lib $FindBin::Bin;).

  • Σκίαση .pmc: αν το Foo/Bar.pmc υπάρχει στον ίδιο κατάλογο με το Foo/Bar.pm, το .pmc υπερισχύει. Τα παλιωμένα αρχεία .pmc είναι κλασική παγίδα τύπου «γιατί η επεξεργασία μου δεν έχει αποτέλεσμα».

  • Ανάλυση του require(EXPR): η require αναλύεται ως ονομαστικός μοναδιαίος τελεστής· το require EXPR + 1 σημαίνει require(EXPR + 1). Χρησιμοποιήστε ρητές παρενθέσεις όταν το όρισμα είναι μη τετριμμένη έκφραση.

  • Αυτο-δημιουργία stash: το require Foo::Bar δημιουργεί τη stash Foo::Bar:: ακόμη και αν το αρχείο λείπει. Επόμενοι έλεγχοι defined &Foo::Bar::some_sub μπορεί να περάσουν το στάδιο «το πακέτο υπάρχει» αλλά να αποτύχουν στο στάδιο «η υπορουτίνα υπάρχει».

  • Το filehandle από γάντζο πρέπει να είναι πραγματικό: Τα tied filehandles αγνοούνται σιωπηλά από το πρωτόκολλο γάντζων· η επεξεργασία ξεπέφτει από το τέλος και η require αναφέρει «not found». Χρησιμοποιήστε πραγματικό typeglob.

  • Το INC πρέπει να είναι πλήρως κατονομασμένο σε κλάσεις γάντζων: το sub Foo::INC { ... } λειτουργεί· το sub INC { ... } μέσα σε package Foo εγκαθιστά το main::INC λόγω ενός σταθερά κωδικοποιημένου κανόνα πακέτου.

  • Η require() είναι δύσκολο να περιτυλιχθεί: Πολλά αρθρώματα επιθεωρούν τη στοίβα κλήσεων για να βρουν τον καλούντα τους. Ένα περιτύλιγμα που προσθέτει πλαίσιο συχνά τα σπάει. Προτιμήστε τους γάντζους ${^HOOK}{require__before} / ${^HOOK}{require__after} (προστέθηκαν στην 5.38) για ιχνηλασία.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • use - require + import κατά τη μεταγλώττιση· ο κανονικός τρόπος για να φέρετε ένα άρθρωμα από το οποίο εξαρτάστε ανεπιφύλακτα

  • do - φορτώνει ένα αρχείο και επιστρέφει την τιμή του σε κάθε κλήση, χωρίς αποθήκευση στο %INC και χωρίς τον κανόνα «πρέπει να επιστρέψει αληθές»

  • import - η μέθοδος που καλεί η use μετά την require· η require δεν την καλεί ποτέ για εσάς

  • @INC - διαδρομή αναζήτησης που συμβουλεύεται για φορτώσεις με bareword και σχετικό όνομα αρχείου· δέχεται συμβολοσειρές καταλόγων, coderefs, αναφορές πινάκων και αντικείμενα ως γάντζους

  • %INC - προσωρινή μνήμη μίας εγγραφής ανά φορτωμένο αρχείο, που κάνει την require ιδεμπoτή και καταγράφει από πού ήρθε κάθε άρθρωμα

  • eval - τυλίξτε την require όταν επιτρέπεται η φόρτωση να αποτύχει