OVH Cloud OVH Cloud

require avec use strict et warnings

26 réponses
Avatar
Asterbing
Bonjour. Je reviens sur le sujet du require abordé dans un récent fil
parce que je n'y réussi pas.

Rappel : soit un script principal en perl (main.cgi) souhaitant utiliser
toutes les déclarations (constantes et variabbles) d'un fichier
modifiable par l'utilisateur (config.cgi). Je souhaitais incorporer
config.cgi dans main.cgi via une ligne "require 'config.cgi';", mais ça
me pose quelque problème. A noter que je teste sous ça dans un
environnement avec Perl Express comme IDE, ActivePerl comme interpréteur
Perl, le tout sous Windows.

Le souci vient du fait que je souhaite aussi mettre une ligne "use
strict;" et lancer le script avec warnings (-w) durant le développement.

Or, lorsque je vérifie la syntaxe dans PerlExpress (F12) avec "use
strict;" actif, le require semble ne pas fonctionner : j'obtiens une
erreur : "Global symbol '$STYPE' requires explicit package name at
main.cgi line 23." sur la première variable devant provenr de
config.cgi.

Si je retire "use strict;", le lien à config.cgi semble marcher (pas
d'erreur de var non déclarée), mais cette fois, c'est le -w qui me met
des warnings de type : "Name 'main::STATCOL' used only once: possible
typo at main.cgi line 240.".

Si je retire "use strict;" et "-w", tout va bien !

Ma question est donc : comment faire accepter ce "require
'config.cgi';" avec "use strict;" et le switch "-w" ?

10 réponses

1 2 3
Avatar
Asterbing
In article <44193dc3$0$6683$,
says...
Ça demande confirmation mais je viens de faire un test d'exécution d'un
script qui se trouve sur un disque différent de celui où est Perl, ça
fonctionne très bien.
Il ne te reste qu'à tester.



Je viens de tester après t'avoir lu et ça marche pas :-( Faut dire que
les config sont exotiques ici ;) Perl est sous c:perlbin, Apache2 et
Perl Express, chacun dans un rep de e:, les virtual hosts encore sur une
autre unité.

Bref, le log errors d'Apache dit :
"(OS 3)Le chemin d'accès spécifié est introuvable. : couldn't spawn
child process: Z:/web/vh/dev/cgi-bin/bonjour.pl, referer: http://dev-
ter/"

Avatar
Asterbing
In article ,
says...
In article <441928a3$0$18309$,
says...
Il suffit d'installer Perl dans c:usr au lieu de c:perl
et tu pourras utiliser #!/usr/bin/perl



Je viens de parler avec le sysadmin : y a aussi linkd.exe livré avec le
reskit win 2003 (dispo gratuit sur le site ms) qui permet de faire un
lien entre un chemin et un autre, pourvu que ce soit sur deux disques
différents et qu'ils soient en NTFS.



Je viens de regarder ce linkd : marche bien avec NTFS effectivement.
Seul pb : l'une des stations est en FAT32 et doit y rester (va savoir,
édouard). Bon, je mets le sujet de côté, revenons au cas require


Avatar
Asterbing
In article ,
says...
Je viens de tester après t'avoir lu et ça marche pas :-( Faut dire que
les config sont exotiques ici ;) Perl est sous c:perlbin, Apache2 et
Perl Express, chacun dans un rep de e:, les virtual hosts encore sur une
autre unité.

Bref, le log errors d'Apache dit :
"(OS 3)Le chemin d'accès spécifié est introuvable. : couldn't spawn
child process: Z:/web/vh/dev/cgi-bin/bonjour.pl, referer: http://dev-
ter/"



OK, pb de chemin perl portable résolu : puisque c'est Apache qui cherche
l'interpréteur Perl, normal qu'un chemin "#!/usr/bin/perl" soit sur la
même unité que l'install Apache.

J'ai donc fait une copie de "c:Perlbin*.*" vers "e:usrbin" et ça
marche. Apache trouve bien Perl !

Bon, reste le vrai sujet du fil, à savoir, choisir entre ces trois voies
:

1) "[our|my] $WAY = 1; "ds config.cgi et "$::WAY" dans main.cgi

2) "use constant WAY => 1;" ds config.cgi et "WAY" dans main.cgi

3) "[our|my] $WAY = 1;" ds config.cgi, "use vars qw($ALLOW_IMG);" et
"$WAY" ds main.cgi

Avatar
Asterbing
In article ,
says...
1) "[our|my] $WAY = 1; "ds config.cgi et "$::WAY" dans main.cgi

2) "use constant WAY => 1;" ds config.cgi et "WAY" dans main.cgi

3) "[our|my] $WAY = 1;" ds config.cgi, "use vars qw($ALLOW_IMG);" et
"$WAY" ds main.cgi



Et bien, puisque je suis condamné à faire ce fil seul (aïe, frappez
pas), voilà ce que j'ai décidé de faire, à moins que dans un sursaut
vous ne m'arrêtiez d'un argument contondant.

Alors, voilà, j'avais ces trois pistes :

1) "[our|my] $WAY = 1; "ds config.cgi et "$::WAY" dans main.cgi
2) "use constant WAY => 1;" ds config.cgi et "WAY" dans main.cgi
3) "[our|my] $WAY = 1;" ds config.cgi, "use vars qw($ALLOW_IMG);" et
"$WAY" ds main.cgi

J'ai écarté la 1) car trop lourd à écrire, la 2 car plus de place à
droite pour les commentaires (mal foutu cette déclar de constante ds
perl, non ?). Je suis donc allé vers 3) avec des modifs.

Tout d'abord, j'ai lu "perldoc use vars" et vu que cette écriture était
obsolète, remplacée par "our". J'ai donc simplement opté pour "our"
plutôt que "my" côté config.cgi et un gros "our()" plutôt que "use
vars" côté main.cgi.

Ce qui donne, par exemple :

--- config.cgi ---
use strict;
our $VAR1 = 1;
our $VAR2 = 12;
our $VAR3 = 123;
1;

--- main.cgi ---
#!/usr/bin/perl
use strict;
our($VAR1, $VAR2, $VAR3);
require 'config.cgi';
...

Voili, voulou ! Des remarques ?

Ah si, je ne sais pas si ça a une importance ou pas, mais est-ce que
l'ordre du our() et require de main.cgi ont un sens ? Je veux dire par
là, est-ce que :

our($VAR1, $VAR2, $VAR3);
require 'config.cgi';

est identique à

require 'config.cgi';
our($VAR1, $VAR2, $VAR3);

Dans la mesure où j'ai cru comprendre que le our() de main.cgi était une
prédéclaration évitant les erreurs "package name" dû au "use strict" et
que ces même var globales pouvaient ensuite être assignée dans
config.cgi sans que la double déclaration ne crée de nouvelles
variables. Bon faut que je me calme là, je fume.

Avatar
Paul Gaborit
À (at) Wed, 15 Mar 2006 15:52:45 +0100,
Asterbing écrivait (wrote):
Rappel : soit un script principal en perl (main.cgi) souhaitant utiliser
toutes les déclarations (constantes et variabbles) d'un fichier
modifiable par l'utilisateur (config.cgi). Je souhaitais incorporer
config.cgi dans main.cgi via une ligne "require 'config.cgi';", mais ça
me pose quelque problème. A noter que je teste sous ça dans un
environnement avec Perl Express comme IDE, ActivePerl comme interpréteur
Perl, le tout sous Windows.

Le souci vient du fait que je souhaite aussi mettre une ligne "use
strict;" et lancer le script avec warnings (-w) durant le développement.


Une solution consiste à *définir* vos variables de configuration
*avant* de faire appel au 'require' (ça permet en plus de fixer des
valeurs par défaut).

Exemple de script :
----------------------------------------
#!/usr/bin/perl -w

use strict;
use warnings;

our $conf_a = 0; # valeur par défaut
our $conf_b; # pas de valeur par défaut

require "$ENV{HOME}/.rcconfig"; # le chemin d'accès au fichier de config

print "$conf_a : $conf_an";
if (not defined $conf_b) {
print "conf_b indéfinin";
} else {
print "conf_b: $conf_bn";
}
----------------------------------------

et le fichier de configuration (dans ~/.rccongig)
----------------------------------------
$conf_a = 1;
1; # indispensable !!!
----------------------------------------

Masi cela ne permet pas de placer un 'use strict' dans le fichier de
configuration lui-même (en fait, c'est largement inspiré de ce que
montre la doc Perl pour la fonction 'do').

Si vous voulez pouvoir mettre le 'use strict' aussi dans le fichier de
configuation, vous êtes obligé de passer par les mécanismes explicites
de Perl ($::var ou l'export de variables).

Une autre méthode passerait par l'écriture d'un analyseur manuel...

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Paul Gaborit
À (at) Thu, 16 Mar 2006 14:02:01 +0100,
Asterbing écrivait (wrote):
[...]
Ce qui donne, par exemple :

--- config.cgi ---
use strict;
our $VAR1 = 1;
our $VAR2 = 12;
our $VAR3 = 123;
1;

--- main.cgi ---
#!/usr/bin/perl
use strict;
our($VAR1, $VAR2, $VAR3);
require 'config.cgi';
...

Voili, voulou ! Des remarques ?


On converge vers une solution similaire (va pour le 'our' dans le
fichier de config afin d'autoriser le 'use strict')... Seul défaut :
si celui qui remplit le fichier de config écrit 'our $VARI' au lieu de
'our $VAR1', il n'y a aucune erreur détectée. C'est pour cela que je
préfère considérer qu'un fichier de configuration ne doit *pas* être
écrit en Perl (l'utilisateur n'est pas programmeur ou si il l'est
alors il peut modifier le script lui-même) et doit donc être analyser
(parser) comme un simple fichier de données avec sa propre syntaxe.

Ah si, je ne sais pas si ça a une importance ou pas, mais est-ce que
l'ordre du our() et require de main.cgi ont un sens ? Je veux dire par
là, est-ce que :

our($VAR1, $VAR2, $VAR3);
require 'config.cgi';

est identique à

require 'config.cgi';
our($VAR1, $VAR2, $VAR3);


En fait cela ne change rien... Si ce n'est qu'en plaçant les
définitions *avant*, on peut en plus prévoir des valeurs par défaut
qui peuvent ensuite être modifées par le fichier de config.


--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Nicolas George
Asterbing wrote in message
:
Si ce n'est justement que je ne vois pas l'intérêt de conserver les
warnings pour le script final une fois uploadé sur le serveur final
(hors test et développement).


Le fait d'uploader le script ne met pas à l'abri de bugs résiduels. Avoir
des logs détaillés pour les diagnostiquer, c'est une bonne chose.

Alors pourquoi lorsque je laisse "my $WAY = 1;" dans config.cgi et
l'utilise avec $::WAY dans main.cgi, ça marche ?


De toute évidence, il te manque toutes les bases sur la déclaration des
variables en Perl. Comme je n'arrive pas à retrouver où dans la doc c'est
fait synthétiquement, je le refais.

Il y a, partout dans perl, des variables globales, avec un système de
paquets pour séparer les espaces de noms. Ces variables portent des noms du
style $main::ARGV, $PerlIO::VERSION, $Text::Wrap::columns, etc. Toutes ces
variables sont disponibles en permanence, depuis n'importe quel fichier /
package / bloc, avec leur nom complet. À titre de cas particulier, les
variables en $main::XXX peuvent s'écrire en plus court $::XXX.

On peut à différents endroits d'un programme écrire « our $truc; ». Ça
déclare que pour la suite, $truc tout court désigne en réalité
$<package>::truc, ou <package> est le package courant du programme. Ainsi,
écrire « our $test; $test = 42; » dans le package main revient à écrire
« $main::test = 42; », ou même « $::test = 42; ». La visibilité de cette
déclaration dure jusqu'à la fin du bloc qui englobe le our. Un bloc, c'est
une paire d'accolades, le corps d'une boucle, ou un fichier évalué, par
exemple. Quand le bloc se termine, l'association du nom court et du nom long
disparaît, mais la variable globale reste modifiée : si l'on a écrit « our
$test = 42; », $main::test vaut bien 42, et continue à valloir 42 bien après
que le $our est oublié ; un accès avec le nom long, ou avec un nouvel our
permet de s'en convaincre.

On peut à différents endroits d'un programme écrire « my $truc; ». Cette
construction crée une _nouvelle_ variable, et l'associe au nom $truc. La
variable dure jusqu'à la fin du bloc contenant le my. À la fin de ce bloc,
cette variable cesse complètement d'exister (sauf si on a pris une référence
dessus). Cette variable n'a strictement rien à voir ni avec
$<package>::truc, ni avec une autre variable $truc créée à un autre endroit
avec my.

Quand Perl rencontre un nom de variable court (sans ::) qui n'est déclaré ni
avec our ni avec my, en cas de use strict (et qui n'est pas une variable
standard) il produit une erreur (à la compilation), et sans use strict, il
se comporte comme si ça avait été déclaré avec our.

Tiens, à ce sujet, n'existe-il pas une astuce pour faire que cette
déclaration du chemin interpréteur soit dépendant de l'OS.


#!/usr/bin/env perl

devrait marcher sur tous les OS décents.

our $::WAY;



Au temps pour moi, ça n'a pas de sens, il fallait écrire « our $WAY; ».


Avatar
Nicolas George
Paul Gaborit wrote in message :
C'est pour cela que je
préfère considérer qu'un fichier de configuration ne doit *pas* être
écrit en Perl (l'utilisateur n'est pas programmeur ou si il l'est
alors il peut modifier le script lui-même) et doit donc être analyser
(parser) comme un simple fichier de données avec sa propre syntaxe.


Je ne suis pas d'accord. Un fichier de config parsé par perl présente de
gros avantages, je trouve. Si l'emballage est bien fait, ça peut être à la
fois tout à fait pratique pour l'utilisateur de base, et présenter des
avantages intéressants pour l'utilisateur avancé (options qui dépendent de
l'environnement ou de la machine, par exemple). Et modifier le script n'est
pas toujours une solution : le script peut être installé globalement, et
c'est assez malpratique si chacun doit se faire une copie pour modifier
quelques options.

En outre, écrire un parseur pour un fichier de conf peut être pénible à
faire proprement, en particulier au niveau de la gestion de l'échappement
(pour pouvoir avoir des « " » dans les chaînes par exemple), des formats
numériques, etc.

Pour éviter que l'utilisateur ait à écrire « $VAR1 = "foo"; », je penche
pour une solution du style :

set VAR1 => "foo";

ou encore plus simplement :

VAR1 "foo";

en me débrouillant pour importer une fonction set ou VAR1 dans le package
qui va exécuter le fichier de config.

Avatar
Asterbing
In article ,
says...
si celui qui remplit le fichier de config écrit 'our $VARI' au lieu de
'our $VAR1', il n'y a aucune erreur détectée. C'est pour cela que je
préfère considérer qu'un fichier de configuration ne doit *pas* être
écrit en Perl (l'utilisateur n'est pas programmeur ou si il l'est
alors il peut modifier le script lui-même) et doit donc être analyser
(parser) comme un simple fichier de données avec sa propre syntaxe.




Oui, je comprends, c'est vrai, mais comme le dit Nicolas G., faut encore
se coltiner l'écriture du parser... Bon, je vais mettre ça dans les
perspectives ;-) Tiens, pourquoi pas un format à la manière des ancien
ini de Win avec

[section]
name=value

Puis, une GUI pour générer ce config.ini de manière sympa... Mais là on
s'écarte un poil des délais que j'ai, enfin que j'avais parce que c'est
censé marcher depuis deux jours (chut).

Avatar
Asterbing
In article <dvbr5f$2748$, nicolas$
s.org says...

De toute évidence, il te manque toutes les bases sur la déclaration des
variables en Perl. Comme je n'arrive pas à retrouver où dans la doc c'est
fait synthétiquement, je le refais.



Oh mais ce Nicolas a l'oeil. C'est vrai que je suis nouveau sur Perl et
qu'un certain nombre de choses surprennent favorablement au début (la
puissance des regex par exemple) alors que d'autres font carrément peur
(l'absence de type explicite des variables par exemple) qd on vient de
choses plus strictes (il y a encore deux semaines, je cherchais pourquoi
on me parlait de compilation alors que c'est de l'interprété, je
cherchais les directives afférantes et, enfin, ne comprenais pas
pourquoi tout ce que j'avais appris du non-usage de variables globales
en entrée/sorties de functions était cassé par les us et coutumes de
choses comme $!).

Je n'avais effectivement pas tout à fait perçu 'my' et 'our' tel que tu
me le décris là, malgré quelques recherches dans la doc.

Merci donc, que dis-je tanqueuillou !

1 2 3