Re: "do" what?
by runrig (Abbot) on Oct 21, 2002 at 22:15 UTC
|
Try use vars qw(%config); instead of my.
Update: Also consider turning the file into a package so you could say something like:
use Myconfig qw(%config);
print $config{this}, "\n";
# etc.
## And in your 'Myconfig' package:
package Myconfig;
use strict;
use warnings;
require Exporter;
use vars qw(%config @ISA @EXPORT_OK);
@ISA = qw(Exporter);
@EXPORT_OK = qw(%config);
$config{this} = "that";
$config{here} = "there";
#etc.
1;
I like this solution better because the place where 'config' is created is self-documenting.
Update: The do block populates a package variable %config in a non-strict environment (your 'do' file), whereas the my creates a lexical variable which never gets populated (I may be wrong, but I think that's it).
Or consider using AppConfig | [reply] [d/l] [select] |
|
|
| [reply] |
|
|
| [reply] |
|
|
|
|
|
|
my creates variables only visible to the current scope, and the closures or blocks defined within it. A my variable is not available to anyone outside the scope, or anything called from within the scope, which was not declared inside it (and even so, that gets tricky).
Example:
my $var1;
$_ = '';
FOO: {
my $var2;
BAR: {
my $var3;
local $_ = 'bar set it';
&foo();
}
GORCH: {
my $var4;
}
}
sub foo {
my $var5;
print "$_\n";
}
Every scope in the above code can see $var1, because they were all declared under the main scope, in which $var1 was created. However, the main scope, and sub foo cannot see any variables declared within FOO: {}, and FOO: {} cannot see $var5, which was declared in sub foo. Furthermore, BAR: {} AND GORCH: {} can see everything except each other's private variables, and sub foo's $var5. sub foo, even when called from FOO: {}, BAR: {}, or GORCH: {} cannot see their private (my) variables. It can see local versions of global (our, $_ sorts) variables though - sub foo, called from bar will print "bar set it".
You may also notice, if you use Data::Dumper; print Dumper \%::; that any files you do are also assigned a package, starting with "_<", and then the relative path. You may be able to use those. my experiments have been unsuccessful, but they weren't very thorough either.
Update: I forgot to mention that my and local both create new copies, and new variables, leaving anything with the same name on an outer scope untouched.
Also fixed HTML entity.
-nuffin zz zZ Z Z #!perl | [reply] [d/l] [select] |
Re: "do" what?
by sauoq (Abbot) on Oct 21, 2002 at 22:19 UTC
|
So, why does strict require the "my %config", but not populate it on "doing the do".
Because your %config and the one in the file you are do'ing are different. Your %config shadows the one in the file. You'll need to declare it as a global.
use vars qw( %config );
If you are using 5.6 or greater, you can write that as our %config; instead.
-sauoq
"My two cents aren't worth a dime.";
| [reply] [d/l] [select] |
Re: "do" what?
by Zaxo (Archbishop) on Oct 21, 2002 at 22:21 UTC
|
#!/usr/bin/perl
use strict;
use warnings;
our %config;
do 'config.cgi';
print keys %config, $/;
Update: Clarification, a file under do cannot see
lexicals in the enclosing scope. The %config that config.cgi writes to is therefore global. When do returns, the lexical %config masks the global one which was just populated.
After Compline, Zaxo
| [reply] [d/l] |
Re: "do" what?
by mojotoad (Monsignor) on Oct 21, 2002 at 22:15 UTC
|
Two observations. First, check $! after the 'do' statement and make sure that the file is indeed being loaded.
Second, inspect config.cgi and ensure that there are no package statements that could be defining %config in a different namespace.
Matt
Update: runrig has it right in this case; the static my %config is not visible in from the point of view of config.cgi; this static %config is therefore masking the global %config variable visible from the do block. | [reply] [d/l] [select] |
Re: "do" what?
by grantm (Parson) on Oct 21, 2002 at 22:25 UTC
|
This parses OK
It shouldn't. The line 'my %config = {};' should trigger the error 'Reference found where even-sized list expected'
Assuming we change it to 'my %config = ();' it still doesn't work, since %config is lexically scoped and the do block doesn't seem to be able to access lexically scoped variables. If you change it to:
our %config = ();
Then you should get the effect you're after.
Having said that, evaluating a config file to set global variables is not a great idea. In fact this is the exact problem XML::Simple was written to solve. If your config file was called scriptname.xml and looked like this:
<config>
<username>zxcvb</username>
<password>zzzzz</password>
</config>
Then you could use it like this:
use XML::Simple;
my $config = XMLin();
print $config->{username};
In real life, you would set explicit values for XMLin's keyattr and forcearray options and you'd probably also want to investigate the caching options. | [reply] [d/l] [select] |
|
|
Or if you don't want to go that far, you can change it to something like:
{
username => 'zxcvb',
password => 'zzzzz',
}
and use it like this:
my $config = do "config.pl";
Makeshifts last the longest. | [reply] [d/l] [select] |
|
|
system("insert malicious command here");
{
username => 'zxcvb',
password => 'zzzzz',
}
If you don't need to trust the keeper of the config file to refrain from malicious or even dumb stuff, why expose yourself to the risk.
Check out YAML for another way to represent complex data structures in config files without needing eval (or "do" in this case). | [reply] [d/l] |
|
|
Re: "do" what?
by Juerd (Abbot) on Oct 22, 2002 at 07:07 UTC
|
You managed to not read or not understand the documentation. The relevant paragraph in perlfunc's do-item is:
do 'stat.pl';
is just like
eval `cat stat.pl`;
except that it's more efficient and concise, keeps track of the
current filename for error messages, searches the @INC
libraries, and updates %INC if the file is found. See "Prede-
fined Names" in perlvar for these variables. It also differs
in that code evaluated with do FILENAME cannot see lexicals
in the enclosing scope; eval STRING does. It's the same,
however, in that it does reparse the file every time you call
it, so you probably don't want to do this inside a loop.
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
| [reply] [d/l] [select] |
*oops*
by cLive ;-) (Prior) on Oct 21, 2002 at 23:06 UTC
|
<blush> No more mystery - I forgot to remove the loop that printed the values of %config when I removed the 'my' statement. (Note to self - d'oh, d'oh, d'oh). It all makes sense now.
</blush>
cLive ;-) | [reply] |