Re: Using eval: $@ isn't returning the error I expect
by haj (Vicar) on Feb 19, 2020 at 23:01 UTC
|
The reason why this fails is that use statements are always evaluated at compile time, even if in a conditional. You could just drop the unless line because if the eval succeeds, then the module is actually loaded.
However, in such a situation I'd just add my own dummy cPanelUserConfig somewhere into my include path and get rid of that ugly string eval in production which would silently hide any errors in the real cPanelUserConfig module.
| [reply] |
|
| [reply] |
|
Just create a file named cPanelUserConfig.pm that contains a single line of:
1;
Place that file in one of the @INC directories.
You can get a list of those directories by running:
perl -le "print for @INC;"
Cheers, Rob
| [reply] [d/l] [select] |
|
Re: Using eval: $@ isn't returning the error I expect
by haukex (Archbishop) on Feb 20, 2020 at 00:05 UTC
|
I see a couple of issues here:
- pryrt pointed out that you're using eval BLOCK syntax with a single string inside the block, that's basically like writing "use cPanelUserConfig;" in your code, i.e. it has no effect, and warnings would have told you "Useless use of a constant ("use cPanelUserConfig;") in void context". Always Use strict and warnings!
- haj pointed out that unless($@){use cPanelUserConfig} will always attempt to load the module. There's the if.pm pragma, but in this case a simple eval "use cPanelUserConfig;" (that's an eval STRING) would be enough to either load the module or not.
- The pattern of checking $@ after an eval is unfortunately common, but it has issues: Bug in eval in pre-5.14.
All in all, since it sounds like you only need to load the module or not, and not actually use any of its functions (?), I would have gone with: eval "use cPanelUserConfig; 1" or warn "Didn't load cPanelUserConfig: $@";.
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
Exactly. The script in question uses a module I installed on the shared server, so cPanelUserConfig must be used for the script to work in that environment -- but not on my local server, where all the modules are in the same place. Thanks!
| [reply] |
|
Thanks, haukex. I tried this:
eval "use cPanelUserConfig; 1" or warn "Didn't load cPanelUserConfig: $@";
as a replacement for the explicit "use" command:
use cPanelUserConfig;
and it ran fine on my own machine, but failed on the host server because on that machine cPanelUserConfig is required in order that a different module be loaded after cPanelUserConfig is loaded. (They treat user-installed modules differently from modules that are part of their default setup.) It would seem that the "eval" command isn't actually loading the cPanelUserConfig module on the host server. Only the explicit "use" statement seems to work there.
| [reply] [d/l] [select] |
|
It would seem that the "eval" command isn't actually loading the cPanelUserConfig module on the host server. Only the explicit "use" statement seems to work there.
If it's not showing a warning, then it is loading it, but there's a difference: eval STRING delays the execution of the use until runtime, while normally it would run at compile time. Try adding a BEGIN { ... } block around the whole line, that'll move the execution back into compile time (see BEGIN in perlmod).
| [reply] [d/l] [select] |
|
Re: Using eval: $@ isn't returning the error I expect
by pryrt (Abbot) on Feb 19, 2020 at 23:05 UTC
|
$ perl -le 'eval { "use gobbledygook;" }; print "ok"'
ok
$ perl -le 'eval { use gobbledygook; }; print "ok"'
Can't locate gobbledygook.pm in @INC ...
$ perl -le 'eval "use gobbledygook;"; print "msg = ($@)" if $@; print
+ "ok"'
msg = (Can't locate gobbledygook.pm in @INC ...)
ok
What you were doing was evaluating the code (the braces make it a code block) that contains a non-empty string; the non "0", non-empty string evaluates true, and the eval block doesn't error, so $@ doesn't get set. What you need to do is either evaluate block of real code in braces, or evaluate a string, not evaluate a string inside a block of code. The second and third in my example both try to use the module; the first (equivalent to your code) does not try to load the module. | [reply] [d/l] |
|
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
Re: Using eval: $@ isn't returning the error I expect
by 1nickt (Canon) on Feb 19, 2020 at 22:47 UTC
|
use Module::Load
eval { autoload 'cPanelUserConfig'; 1 } or do_something_else();
Hope this helps!
The way forward always starts with a minimal test.
| [reply] [d/l] |
|
Thanks, 1nickt
I tried this:
use Module::Load;
eval { autoload 'cPanelUserConfig'; 1 } or print "toast";
and got this error:
syntax error at /Library/WebServer/CGI-Executables/orders/orderFormSal
+esDisplayPreRollout.cgi line 15, near "autoload 'cPanelUserConfig'"
Execution of /Library/WebServer/CGI-Executables/orders/orderFormSalesD
+isplayPreRollout.cgi aborted due to compilation errors.
When I commented out the eval statement, the script ran, which would indicate that Module::Load is indeed installed.
Thanks again! | [reply] [d/l] [select] |
|
use Module::Load; eval { autoload 'cPanelUserConfig'; 1 } or print "toast";
This code works fine for me. Are you sure this is exactly the code you tried?
Also, just to make sure, tell us what version of Perl and the module you're using, as given by perl -MModule::Load -le 'print $]; print $Module::Load::VERSION' (on the command line).
| [reply] [d/l] [select] |
|
Re: Using eval: $@ isn't returning the error I expect
by doctormelodious (Acolyte) on Feb 20, 2020 at 00:52 UTC
|
Seems that after a certain number of indented replies, the text of mine stop showing up on this page. There are just grey rectangles saying that I replied, and I have to click the links therein to actually read them. I'm assuming that's standard for the format used here, yes?
Anyhoo, thanks for the help, everyone. Problem solved! (The eval was not only formatted incorrectly, it needed to be in a BEGIN block, due to the nature of its use by the host server).
| [reply] |
|
In your home node, follow the Settings link ("Edit your: Profile, Settings").
Under "User Settings" (which should come up automatically)
there's a table with "Note Configuration" in the bottom lefthand corner.
Change the values for "Replies header depth:" and "Replies text depth:" to suit.
| [reply] |
|
Ah, that's what I was looking for. Thank you!
| [reply] |