Einbinden von Perl-Code
Ausführung von externem Code mit
do()
Wird die Zahl der Subroutinen in einem Programm immer größer
oder verwendet man dieselben (oder ähnliche) Unterprogramme
immer wieder in verschiedenen Programmen, so sollte man den
Programmcode auf mehrere Dateien verteilen. Es empfiehlt sich,
das Hauptprogramm zusammen mit ein paar wichtigen Subroutinen in
einer Datei zu speichern (die dann als Perl-Skript ausgeführt
wird), und alle anderen Subroutinen (bzw. Klassen bei objekt-orientierter
Programmierung) - in logischen Gruppen zusammengefaßt - in
eigenen Dateien abzulegen.
Um nun Programmcode aus einer zusätzlichen Datei in ein
Hauptprogramm einzubinden, gibt es in Perl verschiedene
Möglichkeiten.
Die einfachste ist die Verwendung der Funktion "do()
".
Hiermit wird Programmcode aus einer externen Datei so wie er dort
abgelegt ist in das aktuelle Programm (also an die Stelle, wo
do
steht) eingebaut und ausgeführt (so als würde
man eval()
auf den Dateiinhalt anwenden).
Datei prog.pl:
#!/usr/local/bin/perl -w
use strict;
print "Erste Zeile des Hauptprogramms\n"; do "funkt.pl"; print "Ende des Hauptprogramms\n";
|
|
Datei funkt.pl:
print "Ausgabe aus 'funkt.pl'\n";
|
|
Erste Zeile des Hauptprogramms Ausgabe aus 'funkt.pl' Ende des Hauptprogramms
|
|
Wie man sieht, erwartet do()
als Argument einen Dateinamen.
Diese Datei wird dann in allen Verzeichnissen gesucht, die im
Array @INC
aufgelistet sind (siehe auch den Abschnitt
Standardmodule).
Befindet sich die gesuchte
Datei in einem Verzeichnis, das nicht standardmäßig
zu @INC
gehört, so kann der Pfad (vor dem Aufruf von
do()
) beispielsweise durch
push(@INC,$verzeichnispfad);
hinzugefügt werden.
Ein Nachteil von do()
ist die Tatsache, das jedesmal,
wenn diese Funktion aufgerufen wird, die entsprechende Datei
geöffnet, gelesen und geparst wird, weswegen sich der Einsatz
z.B. innerhalb einer mehrfach durchlaufenen Schleife nicht gerade
empfiehlt.
[Seitenanfang]
Code-Einbindung mit Hilfe von
require()
Die Funktion require()
bindet im Prinzip genauso wie
do()
Programmcode aus einer externen Datei ein, allerdings
mit dem Unterschied, daß das Einlesen nur einmal geschieht und
Perl beim nächsten Aufruf schon "weiß", daß sich
der entsprechende Code bereits im Speicher befindet und nicht wieder
neu geladen werden muß.
Datei prog.pl:
#!/usr/local/bin/perl -w
use strict;
print "Erste Zeile des Hauptprogramms\n"; require "funkt.pl"; print "Ende des Hauptprogramms\n";
|
|
Datei funkt.pl:
print "Ausgabe aus 'funkt.pl'\n";
|
|
Erste Zeile des Hauptprogramms Ausgabe aus 'funkt.pl' Ende des Hauptprogramms
|
|
Ebenso wie do()
durchsucht auch require()
alle Verzeichnispfade in @INC
.
Ein wesentlicher Unterschied zu do()
besteht aber darin,
daß der Code in der eingebundenen Datei bei der Ausführung
einen "wahren" Wert (true) zurückliefern muß. Im
obigen Beispiel ist dies relativ offensichtlich, da der Aufruf
"print ...
" einen wahren Wert ("1")
zurückgibt (auch wenn er meist nie verwendet wird). Um
sicherzugehen, daß externer Code wirklich zum Schluß
wahr liefert, hat es sich eingebürgert, ans Ende der
Datei eine kurze Zeile mit dem Inhalt "1;
"
anzuhängen - sie bewirkt die Auswertung von "1", was wahr
entspricht und ist der letzte Aufruf der Datei und somit der
Rückgabewert an require()
.
Die Datei funkt.pl aus obigem Beispiel sollte also
besser so aussehen:
print "Ausgabe aus 'funkt.pl'\n";
1;
|
|
Eine zweite Besonderheit von require()
, die bei
der Verwendung von sogenannten Modulen ausgenutzt wird, ist die
Tatsache, daß falls als Argument ein Name angegeben wird, der
nicht einen in Anführungsstrichen stehenden String darstellt,
an diesen Namen automatisch die Endung .pm hinzugefügt wird.
Somit sind die Aufrufe im folgenden Beispiel völlig
äquivalent:
#!/usr/local/bin/perl -w
use strict;
my $dateiname = "extern.pm"; require $dateiname; require 'extern.pm'; require extern; # Automatische Ergänzung von .pm
|
|
Während die Dateiendung .pl üblicherweise für
Skripten/Programme genutzt wird, verwendet man .pm für
Dateien, die Perl-Module enthalten.
[Seitenanfang]
Verwendung von use
Noch leistungsfähiger als require()
ist
use
. Von der Funktion her entspricht
ein use
-Aufruf dem einen von require()
gefolgt von import()
. Letztere ist keine von Perl
vordefinierte Funktion sondern eine Funktion, die in einem
einzubindenden Modul definiert wird und üblicherweise
dazu verwendet wird, um Funktionsnamen zu importieren,
damit sie dann genauso wie andere Funktionen im Hauptprogramm
aufgerufen werden können.
Ein zweiter Unterschied besteht darin, daß use
nicht (wie require()
) an der entsprechenden Stelle zur
Laufzeit des Hauptprogramms abgearbeitet wird, sondern schon bei
der Kompilierung des Programms.
Datei prog.pl:
#!/usr/local/bin/perl -w
use strict;
print "Erste Zeile des Hauptprogramms\n"; use modul; # eigentlich "modul.pm" print "Ende des Hauptprogramms\n";
|
|
Datei modul.pm:
print "Ausgabe aus 'modul.pm'\n";
1;
|
|
Ausgabe aus 'modul.pm' Erste Zeile des Hauptprogramms Ende des Hauptprogramms
|
|
An der Reihenfolge der Ausgabe erkennt man schon, daß der Code
der Datei modul.pm schon abgearbeitet wird, bevor das
eigentliche Hauptprogramm beginnt.
Eine wichtige Konsequenz davon ist, daß man nun nicht mehr
durch eine Zeile wie
push(@INC,$verzeichnispfad);
vor dem use
-Aufruf im Hautprogramm einen zusätzlichen
Suchpfad angeben kann, da use
schon abgearbeitet wird,
bevor überhaupt eine Zeile des Hauptprogramms zur Ausführung
kommt. Zur Lösung dieses Problems kann man den entsprechenden
push
-Befehl in einen
BEGIN { ... }
-Block
einbetten, dessen Inhalt bereits zur Kompilierungszeit aufgerufen wird.
Datei prog.pl:
#!/usr/local/bin/perl -w
use strict;
BEGIN { my $pfad = 'subdir'; push(@INC,$pfad); } print "Erste Zeile des Hauptprogramms\n"; use modul; print "Ende des Hauptprogramms\n";
|
|
Besser ist aber die Verwendung von use lib
,
um einen oder mehrere Pfade zu @INC
hinzuzufügen:
#!/usr/local/bin/perl -w
use strict;
use lib ('subdir');
print "Erste Zeile des Hauptprogramms\n"; use modul; print "Ende des Hauptprogramms\n";
|
|
Datei modul.pm im Unterverzeichnis subdir :
print "Ausgabe aus 'modul.pm'\n";
1;
|
|
[Seitenanfang]