Einbinden von Perl-Code

[ <= ] [ HOME ] [ INHALT ] [ INDEX ] [ => ]

Ausführung von externem Code mittels 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

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. 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 oft durchlaufenen Schleife nicht gerade empfiehlt.


[ <- ] [ HOME ] [ INHALT ] [ INDEX ] [ -> ]

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 schon im Speicher befindet und nicht wieder neu geladen werden muß.

Datei prog.pl:

#!/usr/local/bin/perl -w

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 eine "wahren" Wert (true) zurückliefern muß. Im obigen Beispiel ist dies relativ offensichtlich, da der Aufruf "print ..." eine wahren Wert ("1") zurückgibt (auch wenn er meist nie verwendet wird). Um sicherzugehen, daß externer Code wirklich zum Schluß true 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 true 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

$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.


[ <- ] [ HOME ] [ INHALT ] [ INDEX ] [ -> ]

Verwendung von use()

Noch leistungsfähiger als require() ist die Funktion 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

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, so daß auch diese Funktion zur Kompilierungszeit aufgerufen wird.

Datei prog.pl:

#!/usr/local/bin/perl -w

BEGIN {
  $pfad = 'subdir';
  push(@INC,$pfad);
}
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;


[ <= ] [ <- ] [ HOME ] [ INHALT ] [ INDEX ] [ -> ] [ => ]

Autor: Eike Grote Letzte Änderung: 18.02.1999