Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

jdavidb (1361)

jdavidb
  (email not shown publicly)
http://voiceofjohn.blogspot.com/

J. David Blackstone has a Bachelor of Science in Computer Science and Engineering and nine years of experience at a wireless telecommunications company, where he learned Perl and never looked back. J. David has an advantage in that he works really hard, he has a passion for writing good software, and he knows many of the world's best Perl programmers.

Journal of jdavidb (1361)

Monday May 14, 2007
09:48 AM

How to get at the subroutines within a program

[ #33271 ]

So you have a program that contains routines which should really be in a library. You want to run those routines separately to test them. You don't want to run the program, of course. Or, worse, you want to run those routines for actual production use (you should be shot) without running the program.

I found out how to do this in the middle of the night a couple of weeks ago, from a presentation somebody linked to from here. Jotted down some notes, and now I'm putting it here so I can find it later. :)

require($program);
import qw(routine routine routine);

Or, for testing:

require_ok($program);
import qw(routine routine routine)
ok(routine(1, 2));

This just gets at what the use keyword does, internally.

Update: Okay, this is apparently wrong. :) I didn't try it out at all, though I may have need to at some point. I'm going to leave it here to remind me that this is theoretically possible, although given what dakkar pointed out, it may not be.

Which means somebody's slides were way off. :) (Or else I was completely asleep and didn't understand.)

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Not sure what you're doing there. The require is likely loading the program into the main namespace, just like you already are. The import is importing against main, from main. I bet if you remove it, it works exactly the same.
    --
    • Randal L. Schwartz
    • Stonehenge
  • Let's say you have this prog.pl:

    #!/usr/bin/perl

    sub do_something {
        return 42;
    }

    print "Running\n";

    and this test.pl:

    #!/usr/bin/perl

    require 'prog.pl';
    print "ok 1\n" if do_something()==42;

    Now, running test.pl produces:

    Running
    ok 1

    because the require will execute the program. So, if the program dies because @ARGV is wrong, or somesuch, your test dies as well...

  • If at the top level, you check caller(), you'll find it is false if the script is run as a standalone program, and true if it's loaded as a library.

    Thus, do this at the top level:

    unless(caller) {
       # former top level
       print "Run as a script\n";
    } else {
       # you may drop this if you don't need it
       print "Initializing as a library file\n";
    }
    It'll work now.
    • Thank you. Sounds like this advice was either present in the slides I read, and I missed it (it was middle of the night, up late hacking for work :) ), or else the presenter missed it or only mentioned it orally without including it in the slides.

      --
      J. David works really hard, has a passion for writing good software, and knows many of the world's best Perl programmers
  • Besides your update, import() is a method. When you call methods as functions in Perl, you don't always get what you want.

    I think you'll have more luck checking caller() to see if someone has invoked your program directly.

  • You write your programs as modules, where the main script is actually wrapped in a subroutine (just like the good old days of int main(void)). Now a program is just a set of subroutines and you can use it like every other library of subroutines (including testing it).

    I write about it in Chapter 18 of Mastering Perl [pair.com]
  • Hopefully it wasn't my slides [redhotpenguin.com] that were way off ;-) Here's how I poked at the internals of a program, including global variables. I got the idea from another post here on use Perl, and I hacked out this working program and test.

    phred@pooky ~ $ cat program.pl
    #!perl -w

    use strict;
    use warnings;

    our $var = 0;

    sub addition {
        my ($one, $other_one) = @_;
        my $result = $one + $other_one+$var;
        return $result;
    }

    sub should_die {
        die "oops";
    }

    1;

    phred@pooky ~ $ cat

    • Oops, I forgot the output

      phred@pooky ~ $ perl foo.t
      1..3
      ok 1 - require 'program.pl';
      ok 2 - 1+1+var returns 7
      ok 3 - should_die() died