Comment Perl's @INC est-il construit? (aka Quelles sont les façons d'affecter où modules Perl sont recherchés?)

quelles sont les façons d'affecter l'endroit où les modules Perl sont recherchés? ou, Comment est-Perl @INC construit ?

comme nous le savons, Perl utilise @INC tableau contenant des noms de répertoires pour déterminer où rechercher des fichiers de modules Perl .

il ne semble pas y avoir de FAQ" @INC " complète sur StackOverflow, donc cette question est prévue comme un.

189
demandé sur Community 2010-03-27 00:14:48

3 réponses

nous allons regarder comment le contenu de ce tableau est construit et peut être manipulé pour affecter où L'interpréteur Perl trouvera les fichiers du module.

  1. par Défaut @INC

    interpréteur Perl est compilé avec un @INC valeur par défaut . Pour connaître cette valeur, lancez la commande env -i perl -V ( env -i ne tient pas compte de la variable d'environnement PERL5LIB - voir #2) et dans la sortie vous verrez quelque chose comme ceci:

    $ env -i perl -V
    ...
    @INC:
     /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/site_perl/5.18.0
     /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/5.18.0
     .
    

Note . à la fin; c'est le répertoire courant (qui n'est pas nécessairement le même que le répertoire du script). Il est absent dans Perl 5.26+, et lorsque Perl tourne avec -T (vérification de la teinture activée) .

pour changer le chemin par défaut lors de la configuration du binaire Perl compilation, définir l'option de configuration otherlibdirs :

Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3

  1. variable environnementale PERL5LIB (ou PERLLIB )

    Perl pre-pends @INC avec une liste de répertoires (séparés par deux points) contenus dans PERL5LIB (si elle n'est pas définie, PERLLIB est utilisé) environnement variable de votre shell. Voir le contenu de @INC après PERL5LIB et PERLLIB variables d'environnement ont pris effet, exécuter perl -V .

    $ perl -V
    ...
    %ENV:
      PERL5LIB="/home/myuser/test"
    @INC:
     /home/myuser/test
     /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/site_perl/5.18.0
     /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/5.18.0
     .
    
  2. -I option en ligne de commande

    Perl pre-pends @INC avec une liste de répertoires (séparés par deux points) passés comme valeur de l'option de ligne de commande -I . Cela peut être fait de trois façons, comme d'habitude avec les options Perl:

    • Passer sur la ligne de commande:

      perl -I /my/moduledir your_script.pl
      
    • passez-le via la première ligne (shebang) de votre script Perl:

      #!/usr/local/bin/perl -w -I /my/moduledir
      
    • passer sous PERL5OPT (ou PERLOPT ) variable d'environnement (voir chapitre 19.02 dans programmation Perl )

  3. passer par le lib pragma

    Perl prepends @INC avec une liste de répertoires qui lui est transmise via use lib .

    dans un programme:

    use lib ("/dir1", "/dir2");
    

    sur la ligne de commande:

    perl -Mlib=/dir1,/dir2
    

    vous pouvez aussi supprimer les répertoires de @INC via no lib .

  4. vous pouvez manipuler directement @INC comme un tableau Perl régulier.

    Note: puisque @INC est utilisé pendant la phase de compilation, cela doit être fait à l'intérieur d'un bloc BEGIN {} , qui précède la déclaration use MyModule .

    • ajouter des répertoires au début via unshift @INC, $dir .

    • ajouter des répertoires à la fin via push @INC, $dir .

    • faites tout ce que vous pouvez faire avec un tableau Perl.

Note: les annuaires sont unshifted sur @INC dans l'ordre indiqué dans cette réponse, par exemple @INC par défaut est le dernier dans la liste, précédé de PERL5LIB , précédé de -I , précédé de use lib et de @INC manipulation directe, les deux derniers mélangées dans l'ordre où elles sont en code Perl.

, les Références:

il ne semble pas y avoir un @INC FAQ-post de type sur le débordement de la pile, donc cette question est prévue comme un.

quand utiliser chaque approche?

  • si les modules d'un répertoire doivent être utilisés par plusieurs/tous les scripts de votre site, en particulier s'ils sont exécutés par plusieurs utilisateurs, ce répertoire doit être inclus dans le répertoire par défaut @INC compilé dans le binaire Perl.

  • si les modules dans le répertoire seront utilisés exclusivement par un utilisateur spécifique pour tous les scripts que l'utilisateur exécute (ou si recompiler Perl n'est pas une option pour changer par défaut @INC dans PERL5LIB , généralement lors de l'ouverture de session de l'utilisateur.

    Note: s'il vous plaît soyez conscient des pièges habituels de la variable D'environnement Unix - par exemple dans certains cas, exécuter les scripts comme un utilisateur particulier ne garantit pas de les exécuter avec l'environnement de cet utilisateur mis en place, par exemple via su .

  • Si les modules dans le répertoire doivent être utilisés seulement dans certaines circonstances (par exemple, lorsque le(s) script (s) est exécuté en mode développement/débogage, vous pouvez définir PERL5LIB manuellement, ou passer l'option -I à perl.

  • si les modules doivent être utilisés uniquement pour des scripts spécifiques, par tous les utilisateurs les utilisant, utilisez use lib / no lib pragmas dans le programme lui-même. Il doit également être utilisé lorsque le répertoire à rechercher doit être déterminé dynamiquement pendant exécution - par exemple à partir des paramètres de la ligne de commande du script ou du chemin du script (voir le module FindBin pour le cas d'utilisation très agréable).

  • @INC

    si les répertoires dans @INC doivent être manipulés selon une logique compliquée, soit impossible à trop lourd à mettre en œuvre par la combinaison de use lib / no lib pragmas, puis utiliser direct @INC manipulation à l'intérieur BEGIN {} bloc ou à l'intérieur d'un spécial objet bibliothèque désignée pour la manipulation @INC , qui doit être utilisée par votre(vos) script (s) avant que tout autre module ne soit utilisé.

    un exemple de ceci est la commutation automatique entre les bibliothèques dans les répertoires prod/uat/dev, avec la bibliothèque waterfall dans prod si elle est manquante dans dev et/ou UAT (la dernière condition rend la solution standard" utiliser lib + FindBin " assez compliquée. Une illustration détaillée de ce scénario est dans Comment faire J'utilise les modules beta Perl des scripts beta Perl? .

  • un cas d'utilisation supplémentaire pour manipuler directement @INC est d'être en mesure d'ajouter des références de sous-programmes ou d'objets (Oui, Virginia, @INC peut contenir du code Perl personnalisé et pas seulement des noms de répertoires, comme expliqué dans quand est-ce qu'une référence de sous-Programmes dans @INC est appelée? ).

240
répondu DVK 2018-09-12 12:30:15

en plus des emplacements énumérés ci-dessus, la version OS X de Perl a aussi deux autres façons:

  1. The /Library/Perl/X. xx / fichier AppendToPath. Les chemins listés dans ce fichier sont annexés à @INC à l'exécution.

  2. The /Library/Perl/X. xx / fichier PrependToPath. Les chemins listés dans ce fichier sont prédéfinis à @INC à l'exécution.

15
répondu dgatwood 2014-09-11 19:24:16

comme il a déjà été dit @INC est un tableau et vous êtes libre d'ajouter tout ce que vous voulez.

mon script CGI REST ressemble à:

#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
    push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);
Le sous-programme

est exporté par Rest.pm.

4
répondu Kacper Perschke 2013-05-04 22:16:19