Otto: Eigenes Module

Hallo zusammen,

so ich verstehe etwas mit Perl nicht ich möchte gern ein paar eigene Module schreiben und die benutzen ohne zu installieren.

Dazu habe ich mir ein Grundgerüst mit h2xs -AXc -n NewModule
erzeugt, welches nun wie folgt aussieht:
.
|-- NewModule
|   |-- Changes
|   |-- MANIFEST
|   |-- Makefile
|   |-- Makefile.PL
|   |-- README
|   |-- blib
|   |   |-- arch
|   |   |   -- auto |   |   |       -- NewModule
|   |   |-- bin
|   |   |-- lib
|   |   |   |-- NewModule.pm
|   |   |   -- auto |   |   |       -- NewModule
|   |   |-- man1
|   |   |-- man3
|   |   |   -- NewModule.3pm |   |   -- script
|   |-- lib
|   |   -- NewModule.pm |   |-- pm\_to\_blib |   -- t
|       -- NewModule.t -- test.pl

Das Module NewModule würde ich jetzt gern ohne weitere Umwege in dem Script test.pl nutzen. Dazu habe ich es per use NewModule::NewModule eingebunden.

Jedoch bekomme ich dann die Fehlermeldungen: Can't locate NewModule/NewModule.pm.

Mit der Option -I um den Include Pfad zu ändern habe ich auch schon gespielt, allerdings ohne Erfolg. Ist mein Vorhaben überhaupt möglich?

Wenn ich das Module direkt in den Ordner NewModule kopiere, geht alles wunderbar. Das aktuelle Verzeichnis ist auch im Include Pfad enthalten.

MfG
Otto

  1. hi,

    Jedoch bekomme ich dann die Fehlermeldungen: Can't locate NewModule/NewModule.pm.

    Deinem Tree nach steht das Modul in

    NewModule/lib/NewModule.pm

    Hotti

    1. Hi hotti,

      Deinem Tree nach steht das Modul in

      NewModule/lib/NewModule.pm

      Ja, das ist richtig.

      Wenn ich use NewModule::lib::NewModule benutze dann geht es. Irgendwie logisch :-)

      Danke
      Otto

      1. hi,

        Wenn ich use NewModule::lib::NewModule benutze dann geht es. Irgendwie logisch :-)

        Halt, halt, halt ;-)

        Das geht schon, ist aber bestimmt nicht das, was Du möchtest, denn die Verzeichnisstruktur soll eine Klassenhierarchie abbilden (oder umgekehrt).

        Hier also bitte nochmal drüber nachdenken. Selbstverständlich, und das ist ja das Schöne an Perl, musst Du nicht immer gleich OOP damit fahren. Ein Modul kann durchaus "nur" eine Formelsammlung sein, das ist völlig in Ordnung.

        Hotti

        1. Hi hotti,

          Halt, halt, halt ;-)

          Was immer du mir damit sagen möchtest.

          Das geht schon, ist aber bestimmt nicht das, was Du möchtest, denn die Verzeichnisstruktur soll eine Klassenhierarchie abbilden (oder umgekehrt).

          Die bisherigen Lösungsansätze die ich habe gefallen mir alle nicht so richtig. Was ich im Grunde möchte ist gemeinsame Funktionalität in gemeinsamen Dateien auslagern. Soweit ich das bei Perl verstanden habe, brauche ich dann Module. Also habe ich mir das angeschaut und u.a. das besagte Programm h2xs gefunden und gedacht das es bestimmt sinnvoll ist sich an eine vorgegeben Struktur zu halten. Oder kann man darauf genau so gut verzichten?

          Hier also bitte nochmal drüber nachdenken. Selbstverständlich, und das ist ja das Schöne an Perl, musst Du nicht immer gleich OOP damit fahren. Ein Modul kann durchaus "nur" eine Formelsammlung sein, das ist völlig in Ordnung.

          Auf OOP wollte ich ganz gern verzichten. Da ich mom. mit den Modulen etwas Problem habe und den OO Ansatz von Perl als sehr gewöhnungsbedürftig empfinde.

          Also ich habe in dem Projekt 4 Module in den ich Funktionalität auslagern will. Die Abhängigkeiten sehen so aus:

          A
                    ____|____
                   |         |
                   B         C
                             |
                             D

          Erstelle ich jetzt eine solche Verzeichnisstruktur inkl. Modulen?

          .
          -- A     |-- A.pm     |-- B     |   -- B.pm
              -- C         |-- C.pm         -- D
                      `-- D.pm

          Oder wie würdest du das machen?

          Hotti

          MfG
          Otto

          1. Hallo Otto,

            Die bisherigen Lösungsansätze die ich habe gefallen mir alle nicht so richtig. Was ich im Grunde möchte ist gemeinsame Funktionalität in gemeinsamen Dateien auslagern. Soweit ich das bei Perl verstanden habe, brauche ich dann Module.

            --- ich habe folgenden Lösungsansatz gewählt:
            im cgi-bin befinden sich a.pm, b.pm und Routines.pm.

            a.pm
            --------------------------------
            #!/usr/bin/perl -w
            use strict;
            use Routines  qw(
                                erhoehe_zaehler
                                debug
                            );

            b.pm
            --------------------------------
            #!/usr/bin/perl -w
            use strict;
            use Routines  qw(
                                aendere_daten
                                lade_daten
                                debug
                            );

            Routines.pm
            ---------------------------------
            package Routines;
            require Exporter;
            @ISA        = qw(   Exporter
                          );
            @EXPORT     = qw(
                                aendere_daten
                                erhoehe_zaehler
                                debug
                                lade_daten
                          );
            @EXPORT_OK  = @EXPORT;

            use strict;
            sub erhoehe_zaehler {
                my ( $zaehler, $wert ) = @_;
                ...usw...
            }

            Alle ausgelagerten Funktionalitäten befinden sich als Subroutinen in Routines.pm. Je nachdem, welche ich benötige, binde ich sie am Anfang des Scripts ein. In @EXPORT müssen alle Subroutinen stehen, damit sie exportiert werden können. Ich finde diese Lösung sehr übersichtlich und deutlich einfacher, als _richtige_ Module zu bauen und zu installieren. Ich habe zusätzlich noch Templates.pm als Sammeldatei für Vorlagen und Variablen, die ich so konzentriert an einer Stelle für das ganze Projekt zusammen habe und entsprechend des Bedarfs in den Scripten einbinde.

            Besten Gruß
            JOhnnY

            1. Hi Johnny B.,

              Wenn ich deinen Vorschlag nehme, dann brauche ich auch gleich gar nichts auslagern. Da am Ende alles in einer Datei steht.

              Wenn du nicht alles Exportieren willst, dann schau dir mal %EXPORTER_TAGS an, dann braucht man nicht Pseudodateien die keine Aufgabe haben.

              MfG
              Otto

              1. Hallo Otto,

                Wenn ich deinen Vorschlag nehme, dann brauche ich auch gleich gar nichts auslagern. Da am Ende alles in einer Datei steht.

                Das verstehe ich nicht? Die Scripte a.pl und b.pl (das habe ich in meiner Darstellung leider falsch gemacht, dort steht a.pm und b.pm) sind einzelne Dateien und die gemeinsamen Routinen sind in eine weitere Datei ausgelagert. Ist nicht das, was Du wolltest?

                Wenn du nicht alles Exportieren willst, dann schau dir mal %EXPORTER_TAGS an, dann braucht man nicht Pseudodateien die keine Aufgabe haben.

                Wo sind denn Pseudodateien ohne Aufgabe?

                Besten Gruß
                JOhnnY

                1. Hi Johnny B.,

                  Streich meine Aussage aus dem Protokoll.

                  Die Endung pm hat mich wohl etwas verwirrt. Ich habe mir folgendes zusammengereimt:

                  Die Datei Routines.pm enthält alle ausgelagerten Funktionen. Die Dateien a.pm und b.pm binden diese dann mit use ein und Importieren die vollständige Funktionalität. Nun wird von a.pm und b.pm nur eine Untermenge der Funktionen von Routines.pm exportiert um die Schnittstelle klein zu halten.

                  Ich weiß das es da nicht steht, habe nicht gründlich genug gelesen.

                  Habe auch mittlerweile eine Struktur für das Projekt erstellt, die meiner Ansicht nach nicht perfekt ist, jedoch für dieses Projekt ausreichend.

                  Eine herzlichen dank an alle die sich an der Diskussion beteiligt haben.

                  MfG
                  Otto

          2. moin,

            Oder wie würdest du das machen?

            Statt Modulen Libraries schreiben, die mit require eingebunden werden. Für diese Libs die in Perl vorhandene Verzeichnissstruktur nutzen und eigene Module/Libs in das dafür vorgesehene Verzeichnis site/lib kopieren.

            Gib mal @INC aus, da stehen die Verzeichnisse, in denen Perl nach Modulen oder Libraries sucht. Da ist auch . dabei, das Verzeichnis, was $0 entspricht.

            Hotti

            1. Hi hotti,

              Statt Modulen Libraries schreiben, die mit require eingebunden werden. Für diese Libs die in Perl vorhandene Verzeichnissstruktur nutzen und eigene Module/Libs in das dafür vorgesehene Verzeichnis site/lib kopieren.

              Warum jetzt auf einmal keine Module mehr? Habe mir gedacht dann ist auch der spätere Sprung zu OO einfacher. Hast du weiter oben nicht gesagt das die Verzeichnisstruktur die Hierarchie abbilden soll?

              Gib mal @INC aus, da stehen die Verzeichnisse, in denen Perl nach Modulen oder Libraries sucht. Da ist auch . dabei, das Verzeichnis, was $0 entspricht.

              Ich weiß das dort das aktuelle Verzeichnis drin steht. Was du mir jetzt damit konkret sagen willst wird mir nicht klar.

              P.S.: Bei meiner Anwendung handelt es sich um keine Web-Anwendung, sie läuft rein lokal.

              Sorry Hotti, ich kann deine Gedanken einfach nicht nachvollziehen und nicht erkennen in welche Richtung du denkst und mich lenken möchtest. Trotzdem danke für deine bisherige Hilfe.

              Hotti

              MfG
              Otto

  2. so ich verstehe etwas mit Perl nicht ich möchte gern ein paar eigene Module schreiben und die benutzen ohne zu installieren.

    Dazu habe ich mir ein Grundgerüst mit h2xs -AXc -n NewModule
    erzeugt, welches nun wie folgt aussieht:

    damit erzeugst du ein Grundgerüst um das Modul zu installieren - nicht um es zu benutzen!

    Struppi.

    1. Hi Struppi,

      damit erzeugst du ein Grundgerüst um das Modul zu installieren - nicht um es zu benutzen!

      Das heißt wenn ich ein paar lokale Module erstellen möchte, die ich ohne Installation benutzen möchte, kann ich drauf verzichten?

      MfG
      Otto

      1. damit erzeugst du ein Grundgerüst um das Modul zu installieren - nicht um es zu benutzen!

        Das heißt wenn ich ein paar lokale Module erstellen möchte, die ich ohne Installation benutzen möchte, kann ich drauf verzichten?

        Im Prinzip ja, wobei ich aber sagen muss ich habe noch nie ein Modul gebaut, dass man mit make installieren konnte. Was sicher seine Vorteile hat.

        Aber wenn es dir nur um eigene Module, in Form von .pm Dateien geht, dann solltest du ein Verzeichniss dafür einrichten. Das kann irgendwo auf der Festplatte liegen (unter Linux gibt es dafür spezielle Verzeichnisse, windows bietet sowas nicht) und dann baust du in alle deine Skripte use lib "/pfad/zum/verzeichniss/"; ein

        Struppi.

        1. Hi Struppi,

          Aber wenn es dir nur um eigene Module, in Form von .pm Dateien geht, dann solltest du ein Verzeichniss dafür einrichten. Das kann irgendwo auf der Festplatte liegen (unter Linux gibt es dafür spezielle Verzeichnisse, windows bietet sowas nicht) und dann baust du in alle deine Skripte use lib "/pfad/zum/verzeichniss/"; ein

          Es geht nur darum gemeinsame Funktionalität zu Kapseln, so das die gut wiederverwendbar ist.

          Vermutlich ist dein Vorschlag für das kleine Projekt der sinnvollste.

          Danke
          Otto

          1. Aber wenn es dir nur um eigene Module, in Form von .pm Dateien geht, dann solltest du ein Verzeichniss dafür einrichten. Das kann irgendwo auf der Festplatte liegen (unter Linux gibt es dafür spezielle Verzeichnisse, windows bietet sowas nicht) und dann baust du in alle deine Skripte use lib "/pfad/zum/verzeichniss/"; ein

            Es geht nur darum gemeinsame Funktionalität zu Kapseln, so das die gut wiederverwendbar ist.

            Also innerhalb einer Anwendung, dann brauchst du eigentlich nichts zu machen. Da, wie du schon selber festgestellt hast das aktuelle Verzeichniss i.d.R. im Suchpfad ist.

            Struppi.

  3. Hallo Otto,

    ich habe selten soviel dämlichen Ratschlag wie in diesem Thread gelesen.

    Eins vorweg: mit deinem Ansatz bist du grundsätzlich auf dem richtigen Weg (also das Gestalten und Verpacken von Modulen als CPAN-konforme Distribution), lasse dich nicht von den Anfängern Struppi und hotti wirr machen. Behalte dieses Verzeichnisgerippe bei, und scheue dich auch nicht, deine Distro auf dem normalen Wege (also make install) zu installieren, wenn du mit den Modulen fertig und zufrieden bist. Solange du noch mit der Entwicklung beschäftigt bist, bewege dich ins Basisverzeichnis (wo sich Makefile.PL befindet), und es hilft ein prove -b nach dem make-Schritt (analog prove -l vor dem make-Schritt), bzw. perl -Mblib ... nach dem make-Schritt (analog perl -Ilib ... vor dem make-Schritt), um die von dir angegebene Fehlermeldung zu vermeiden.

    Als Ersatz für h2xs ist dringend Module::Starter::PBP zu empfehlen, insbesonders weil die Tests dann gleich an der richtigen Stelle landen. Lösche test.pl, behalte das t/-Verzeichnis. Mit Module::Starter::PBP kannst du auch gleich eine Hierarchie von Modulen anlegen, nicht nur ein einzelnes wie bei h2xs.

    Ich finde deinen Baum in https://forum.selfhtml.org/?t=195566&m=1309141 zu abstrakt, um konkreten Rat dazu geben zu können. Ich ersetze es daher mal aufs Geratewohl mit angenommenen Namen.

    Hierarchie von Klassen/Packages:

    Foo::Bar
             _______|______
             |            |
    Foo::Bar::Config  Foo::Bar::Parser
                          |
                      Foo::Bar::SpecialisedParser

    Resultiert in Hierarchie von Verzeichnissen/Dateien:

    Foo-Bar-0.01/lib/Foo/Bar.pm
    Foo-Bar-0.01/lib/Foo/Bar/Config.pm
    Foo-Bar-0.01/lib/Foo/Bar/Parser.pm
    Foo-Bar-0.01/lib/Foo/Bar/SpecialisedParser.pm
    Foo-Bar-0.01/t/*.t
    Foo-Bar-0.01/Makefile.PL (oder Build.PL)
    Foo-Bar-0.01/README
    Foo-Bar-0.01/Changes
    Foo-Bar-0.01/MANIFEST (erzeugt durch Toolchain)
    Foo-Bar-0.01/META.yml (erzeugt durch Toolchain)

    Hinweise dazu: Foo-Bar-0.01 ist der Distroname. In 95% der Fälle kommt er vom Hauptmodul der Distro + Versionsnummer, ein bekanntes Gegenbeispiel ist die Distro namens libwww-perl. Also, daher nicht davon verwirren lassen, dass der Name des Packages Foo::Bar augenscheinlich mehrmals umgesetzt wird!

    Um deine Distro auf einen anderen Rechner umzuziehen, make dist und du bekommst ein Archiv, welches sich über die reguläre Toolchain installieren lässt, natürlich auch mit dem manuellen Standardverfahren auspacken; perl Makefile.PL; make; make test; make install.

    1. ich habe selten soviel dämlichen Ratschlag wie in diesem Thread gelesen.

      Danke, ich hoffe deiner ist zielführender.

      Eins vorweg: mit deinem Ansatz bist du grundsätzlich auf dem richtigen Weg (also das Gestalten und Verpacken von Modulen als CPAN-konforme Distribution), ..

      ob er das will, ist zweifelhaft. Nicht jedes Modul muss CPAN konform sein.

      .. und scheue dich auch nicht, deine Distro auf dem normalen Wege (also make install) zu installieren,

      Soweit ich den Thread verfolgt habe, sprach niemand von installieren sondern im gegenteil.

      so ich verstehe etwas mit Perl nicht ich möchte gern ein paar eigene Module schreiben und die benutzen ohne zu installieren.

      Anstatt dich zu ereifern, hättest du vielleicht nochmal Otto Posting lesen sollen.

      Um deine Distro auf einen anderen Rechner umzuziehen, make dist und du bekommst ein Archiv, welches sich über die reguläre Toolchain installieren lässt, natürlich auch mit dem manuellen Standardverfahren auspacken; perl Makefile.PL; make; make test; make install.

      Vorausgesetzt make ist auf dem System installiert. Ich hab sowas in den 12 Jahren die ich mit Perl programmiere noch nie gebraucht. Trotzdem habe ich Spaß an Perl. Wenn ich das so verbissen sehen würde wie du, hätte ich ihn sicher schon längst verloren.

      Struppi.

      1. Ich bin nicht verbissen, habe nur die besten Absichten. Komm mal zum GPW2010, ich geb dir ein Bier aus und wir reden drüber.

    2. Hi CPAN,

      Hallo Otto,

      ich habe selten soviel dämlichen Ratschlag wie in diesem Thread gelesen.

      Solche Aussagen helfen doch nun wirklich keinen weiter.

      Eins vorweg: mit deinem Ansatz bist du grundsätzlich auf dem richtigen Weg (also das Gestalten und Verpacken von Modulen als CPAN-konforme Distribution),

      Wobei dieses keine Anforderung ist und nicht zwingend Notwendig ist, lediglich ein schöner Nebeneffekt.

      lasse dich nicht von den Anfängern Struppi und hotti wirr machen.

      Unsachlicher geht es kaum noch.

      Solange du noch mit der Entwicklung beschäftigt bist, bewege dich ins Basisverzeichnis (wo sich Makefile.PL befindet)

      Meinst du ich soll die pm Datei aus dem Lib-Verzeichnis in das Wurzelverzeichnis kopieren?

      MfG
      Otto

      1. bewege dich ins Basisverzeichnis (wo sich Makefile.PL befindet)
        Meinst du ich soll die pm Datei aus dem Lib-Verzeichnis in das Wurzelverzeichnis kopieren?

        Nein, cd/chdir ist gemeint. Die genannten Befehle prove -b⫽-l und perl -Mblib⫽-Ilib ... greifen nur richtig von dieser Stelle aus.