in reply to How to import "global" variables into sub-scripts from main script?
our creates an alias in the current lexical scope. The largest scope Perl knows is the file scope, there's nothing like "script-plus-subscripts scope" (or, as you call it, "global" scope). Use fully qualified names if you want to access variables globally, $main::DEBUG is a valid name (and would clearly signal to me something is wrong).
The advice to use strict and modules comes from experience. Your specific use case might be different, but I doubt it. I've worked with a large codebase that required scripts instead of using modules - it was a nightmare (See for example Wrong + Right = Even Worse that describes one of the issues it had).
Feel free to use scripts instead of modules and throw away strict. Just don't be surprised later when everything breaks and no one wants to touch the monster.
Update: There's another possibility, even more horrible, which makes it possible to access our and even my variables in the included script:
sub run {
my ($f) = @_;
open my $in, '<', $f or die $!;
my $code = do { local $/; <$in> };
eval $code
}
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re^2: How to import "global" variables into sub-scripts from main script?
by Polyglot (Chaplain) on Mar 22, 2021 at 09:38 UTC
|
I appreciate the prompt response, thank you.
So, is there really no way to import the variables from the main script? I thought perl was supposed to be good at passing variables.
I don't have a script named "main". I have no idea what perl would think if I tried $main::DEBUG. Is that supposed to "import" the $DEBUG variable? Would I need to do something more like this: $MyPerlScript.pl::DEBUG? That just looks tacky and ugly, in my opinion.
It makes no sense to me that the error message would complain about a variable not having been imported--if in fact it's not possible to "import" a variable in the first place. That's the part that gets me, I guess.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
> I don't have a script named "main"
But you have a package called "main" (unless you declare a package in your main script).
If you have no idea what Perl would do, try it. You already know how to create a Perl script and run it.
> That just looks tacky and ugly
Yes, it looks ugly, because it is ugly.
Note that Variable "$x" is not imported is not an error, it's a warning. It's explained in perldiag:
(S misc) With "use strict" in effect, you referred to a global
variable that you apparently thought was imported from another module,
because something else of the same name (usually a subroutine) is
exported by that module. It usually means you put the wrong funny
character on the front of your variable.
Which doesn't seem helpful, so your confusion is understandable. It seems the explanation needs an addition (volunteers?)
Update: The required sub-scripts should have failed to compile under strict. If you're using do instead of require, you should check $@ and $!.
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Update: The required sub-scripts should have failed to compile under strict. If you're using do instead of require, you should check $@ and $!.
Remember, I wasn't using strict in the sub-files before. I had assumed that when I said "use strict;" in the main file, and then was bringing in the other subroutines via "require subfile.pl;" that the "strict" had applied to the entire global context. Remember, the global variables are all correctly shared among the files--so why wouldn't strict be shared, too?
In any case, I had no issues compiling until I added "strict" to the sub-file.
I'm not using "do" anywhere in the entire script at this point.
| [reply] [Watch: Dir/Any] |
|
|
|
|
|
|
our $DEBUG = $DEBUG || 0;
It didn't work. I still get a whole slew of $DEBUG related errors in the log. So much for attempting to declare them and just take the first error on the chin to save the rest.
Strict will just have to go this time...it seems to oppose all of what caused me to fall in love with Perl in the first place. I was sick of all the constraints of Pascal, and the strict types...and Perl just seemed to know when something should be a number, or a string, etc. without needing tedious conversion routines or such a strict (strait-jacket) approach.
| [reply] [Watch: Dir/Any] [d/l] |
|
|
|
|
I don't have a script named "main".
main is the default package if no package statement has
declared any other.
I have no idea what perl would think if I tried $main::DEBUG.
This is the "fully qualified" form of a package-global name.
It is always valid.
Even under strict, fully-qualified package globals can
always be accessed with or without pre-declaration.
Some examples:
Win8 Strawberry 5.30.3.1 (64) Mon 03/22/2021 6:33:58
C:\@Work\Perl\monks
>perl
use strict;
use warnings;
package Bar {
# package-globals can always be accessed in fully-qualified form
$main::foo = "hi, i'm assigning this in " . __PACKAGE__ . "\n";
}
print "A: this is being printed from default package ", __PACKAGE__, "
+\n";
# global $foo not yet declared in main: must access fully-qualified
print "B: i'm accessing this from ", __PACKAGE__, ": $main::foo";
our $foo; # declare global $foo in package main
print "C: i'm accessing this from ", __PACKAGE__, ": $foo";
^Z
A: this is being printed from default package main
B: i'm accessing this from main: hi, i'm assigning this in Bar
C: i'm accessing this from main: hi, i'm assigning this in Bar
Give a man a fish: <%-{-{-{-<
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Keep in mind that I have only one file among all of them which uses the shebang line--just the main script. These attached files are not designed to be independent, and could probably work just as well given a ".txt" suffix. Though I have put ".pl" as their suffix, I do not set their executable bits on the server, i.e. they are chmod 640 instead of 755 (running on linux). Furthermore, they basically return true immediately, without executing anything. All they do is provide space for me to organize my various subroutines.
Taken together, they average over 850 lines per file. I'd like to bring that down further, as anything over about 600 lines begins to get unwieldy for me and I have a harder time finding things or remembering where to look for them. I never realized that perl wants to be an all-in-one-big-file script, with no way to share global variables!
Again, I'm not writing or using packages. I'm just spreading out my script into multiple files for organizational purposes.
Next, I suppose, I'll have to write a separate script that combines all of my individual files into a single file on the server prior to run-time. Sigh. Wow. I can't believe this. I always imagined Perl to be more capable--this seems such a simple thing to be able to do, not even a majorly complex problem.
| [reply] [Watch: Dir/Any] |
|
|
| [reply] [Watch: Dir/Any] |
|
Variable "%s" is not imported%s
(S misc) With "use strict" in effect, you referred to a global variable that you apparently thought was imported from another module, because something else of the same name (usually a subroutine) is exported by that module. It usually means you put the wrong funny character on the front of your variable.
I did run across that one earlier in my quest for a resolution, but found it of no use to me--too esoteric and short on detail. I have no idea what the "right" "funny character" should be--or even what a "funny character" is supposed to refer to--the dollar sign, perhaps? What else would one prefix a scalar variable with?
I guess there's no easy answer. Best, in my case, might be just to turn "strict" back off and continue my troubleshooting without its bungling "help." Sorry to have troubled the waters here for nothing.
| [reply] [Watch: Dir/Any] |
|
Re^2: How to import "global" variables into sub-scripts from main script?
by Polyglot (Chaplain) on Mar 22, 2021 at 15:16 UTC
|
Just don't be surprised later when everything breaks and no one wants to touch the monster.
Whether it breaks or not, or even if I wrote it with the combined impeccable abilities of all you experts here, when I'm no longer able to maintain it, it is highly unlikely that anyone else will; not because they wouldn't want to, but because they don't know the first thing about programming, much less Perl. I honestly do not personally know another Perl programmer. I have never met one in my entire sojourn in this part of the world. My Perl books come from Amazon--from America; I don't recollect seeing any such in bookstores in my area. Perl may be a well-established fact in some parts, but not where I am. Here, people learn Java, or C++, or .NET, etc.
Your "horrible" possibility looks too scary for me. I don't dare try it.
Because I have never been able to grasp abstractions like OO, references, etc., I've never seen modules as an option for me. I can only do what I have ability for. If I don't understand something, even copy/pasting from someone else will almost never work for me, as I'm unable to adapt to my needs that which I do not understand in the first place. So I generally do all of my own programming, simple though it may be. For some blessed reason I do usually understand regex quite well--I guess it's not so abstract.
After a few minutes without strict I was able to find the troublespot and everything is working well again. Strict is still in use in my main script file, as it always was. It causes no problems there, but it throws a fit if brought into any of the sub-files.
...ACTUALLY, I just confirmed that redeclaring the globals in the sub-script still allows their values to pass from the main script, and that "strict" seems satisfied with that. Honestly, it smacks of overkill to me to have to declare variables repeatedly--if I were to add "strict" to my other files, the globals would have to be repeated in each of them too (I started with just the main MYSQL sub-script). AND, after adding all those global variables, strict had nothing at all to say--that was the only thing between the script running or not running. It was no idle "warning." It was a "kill script" level error to simply not have redeclared my global variables. I don't find this behavior helpful. I know, I'll probably get a ton of downvotes for speaking my mind, as I have with my other posts here, but I have never been a conformist for the sake of popularity. Now, if "strict" had actually said anything useful to me after I had gotten past the globals issue, i.e. if it had told me something about my code that had earlier escaped my notice, and that was an important weakness, I might have a different view. But, nope. It was just its own rigidity. Everything would have worked fine without it.
| [reply] [Watch: Dir/Any] [d/l] |
|
Honestly, it smacks of overkill to me to have to declare variables repeatedly
One of the major functions of strict is to protect against typos in variable names. How can it detect a misspelled variable name if it doesn't know (via a declaration) what the correct name is?
Your answer seems to be "it should know because I declared it in the master script", but what if I write a different master script which uses your auxiliary script without declaring that variable? Because you split things up into multiple scripts and incorporate them into the master using require, each one needs to be able to stand alone, and that includes making its own variable declarations, as well as setting its own pragmas (strict, warnings, etc.).
if "strict" had actually said anything useful to me after I had gotten past the globals issue, i.e. if it had told me something about my code that had earlier escaped my notice
Perl tries, but it can't read your mind. Judging by the additional diagnostic messages for the "not imported" errors, it seems that what Perl thinks went wrong is that you imported some_sub() from another module, then mistakenly referred to it as $some_sub. That's not what you were actually doing, of course, but, since it's what Perl thought you were doing, that's the problem it tried to help you solve.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|