Einige Kernfunktionen in Perl können nur schwer überschrieben werden – jedenfalls für die meisten von uns. Eine dieser Funktionen ist require
. Um das Verhalten solcher Funktionen zu verändern oder auf die Ausführung der Funktionen reagieren zu können, wurde in Perl 5.38 der Spezialhash %{^HOOK}
eingeführt.
In diesem Hash werden Codereferenzen gespeichert. Der Schlüsselname wird zusammengesetzt aus dem Namen der Funktion, zwei Unterstrichen _
und der Phase wann diese Codereferenz ausgeführt wird (derzeit gibt es nur die zwei Phasen before
und after
).
Im Beispiel von require
können also Codereferenzen zu den Schlüsseln require__before
und require__after
gespeichert werden.
Beide Hooks bekommen als einzigen Parameter den Dateinamen übergeben, dabei wird der Paketname in einen Pfad umgewandelt (MIME::Base64
wird dabei zu MIME/Base64.pm umgewandelt).
Bei der Verwendung ist es wichtig, dass die Hooks vor dem Einbinden weiterer Module gesetzt werden. Daher muss man die entsprechenden Hooks in einem BEGIN{}
-Block definieren:
#!/usr/bin/perl
use v5.38;
use strict;
use warnings;
BEGIN {
%{^HOOK} = (
require__before => sub ($path) {
say "I try to require $path...";
},
require__after => sub ($path) {
if ( $INC{$path} ) {
# loading the module was successful
say "welcome to the app, $path!";
}
}
);
}
use Mojo::File;
say "done...";
require__before
wird dabei aufgerufen, bevor %INC
geprüft, @INC
durchsucht, INC-Hooks aufgerufen werden. require__after
wird unabhängig vom Erfolg aufgerufen, aus diesem Grund wird in dem Beispielcode auch der Eintrag in %INC
geprüft. Der before-Hook wird in der Reihenfolge der require
-Aufrufe ausgeführt, der after-Hook in umgekehrter Reihenfolge.
Diese Hooks können gut zum Debugging genutzt werden, wenn man wissen möchte, welche Module eingebunden werden und wer diese Module einbindet:
use v5.38;
my %modules;
use Data::Dumper;
BEGIN {
%{^HOOK} = (
require__before => sub ($path) {
my @info = caller(0);
$modules{$path}->{$info[0]}++;
},
);
}
use OPM::Validate;
use Mojo::File;
print Dumper \%modules;
say "done...";
Permalink: /2023-07-28-kaptan-hook-und-die-module