tags:

views:

825

answers:

6

Hi I am using a perl script written by another person who is no longer in the company. If I run the script as a stand alone, then the output are as expected. But when I call the script from another code repeatedly, the output is wrong except for the first time.

I suspect some variables are not initialised properly. When it is called standalone, each time it exits and all the variable values are initialised to defaults. But when called from another perl script, the modules and the variable values are probably carried over to the next call of the script.
Is there any way to flush out the called script from memory before I call it next time?

I tried enabling warning and it was throwing up 1000s of lines of warning...!

EDIT: How I am calling the other script:

The code looks like this:

do "processing.pl";
...
...
...

process(params); #A function in processing.pl
...
...
...
+3  A: 

If you want to force the module to be reloaded, delete its entry from %INC and then reload it.

For example:

sub reload_module { 
    delete $INC{'Your/Silly/Module.pm'};
    require Your::Silly::Module;
    Your::Silly::Module->import;
}

Note that if this module relies on globals in other modules being set, those may need to be reloaded as well. There's no easy way to know without taking a peak at the code.

friedo
Module::Reload will handle those details for you, but also note my comment to tsee's answer.
brian d foy
@Brian: does Module::Reload deal with the issues that Module::Unload does not? Can it, in fact?
Jonathan Leffler
+4  A: 

If you don't want to rewrite/fix the script, I suggest calling the script via exec() or one of its varieties. While it is not very elegant to do, it will definitely fix your problem.

Dave Vogt
How does this fix the problem? Are you thinking about forking the processing then execing?
brian d foy
The trouble with using 'exec' is that you can't call the function 'process' because it hasn't been loaded into the program. So, you'd have to worry about how to get the information back from the exec'd program in a format that can be managed by Perl. I suppose some sort of formatted output that generated a string that, when eval'd, initialized a variable might work - but it might be simpler just to get on with cleaning up or rewriting the code.
Jonathan Leffler
A: 

Another possibility (just thinking aloud here) could be to do with the local directory? Are they running from the same place. Probably wouldn't work the first time though.

Another option is to use system ('doprocessing.pl');. Lazily, we do this with a few scripts to force re-initialisation of a number of classes/variables etc. And to force the log files to rotate properly.

edit: I have just re-read your question, and it would appear that you are not calling it like this.

Xetius
+1  A: 

Unloading a module is a more difficult task than simply removing the %INC entry of the module. Take a look at Class::Unload from CPAN.

tsee
Note that Class::Unload is not a direct solution to this problem. It's goal is to clean out anything inside a particular package. It does not undo anything else that a module might have done, such as messing with Perl special variables, defining anything in other classes (something I do frequently), or any of the other things a module might do that doesn't involve the symbol table.
brian d foy
You're right of course. I though I remembered that the Class::Unload docs had a CAVEAT section, but I was mistaken.
tsee
+5  A: 

Hi I am using a perl script written by another person who is no longer in the company. I tried enabling warning and it was throwing up 1000s of lines of warning...!

There's your problem right there. The script was not written properly, and should be rewritten.

Ask yourself this question: if it has 1000s of warnings when you enable strict checking, how can you be sure that it is doing the right thing? How can you be sure that it is not clobbering files, trashing data sets, making a mess of your filesystem? Chances are it is doing all of these things, either deliberately or accidentally.

I wouldn't trust running an error-filled script written by someone no longer with the company. I'd rewrite it and be sure that it was doing what I needed it to do.

Ether
Even if there are no warnings, you still don't know if it is doing the right thing. Warnings change with versions of Perl, so there's not much you can infer from merely getting lots of warnings.
brian d foy
I'd infer a sloppy codebase that should be prioritized for rewriting :) But agreed, the absence of warnings is not indicative of the absence of errors.
Ether
+1  A: 

Are you sure that you need to reload the module? By using do, you are reading the source every time and executing it. What happens if you change that to require, which will only read and evaluate the source once?

brian d foy