WebReference.com - Perl Module Primer (3/5)
Perl Module Primer
Having defined our simple module, let's have a look at a script that makes use of it:
#!/usr/bin/perl use SayHello; print SayHello::hello_message()."\n";
Again, the code is pretty straightforward. Chances are you've used the use command in Perl before, to make use of compiler pragmas (such as the highly recommended use strict), or functions in the standard library modules or specific modules that you've downloaded from CPAN or some other repository. Like the module definition itself, however, there's more than meets the eye even with the simple code segment above; so let's take a closer look to reveal some additional details about module usage.
Using Modules With use
The simplest way to pull a module into your script so that you can use its functions is to use Perl's use command. use automatically searches all the paths in the array @INC until it finds a file with the name you specified and a .pm extension. In our case, it will look through each directory, one at a time, until it finds the file SayHello.pm. You can easily see what directories are assigned to the @INC array on your system with this code:
perl -e "print join(qq|\n|,@INC).qq|\n|"
(We use qq in the above example to avoid problems when using single quotes on a Windows command line. On UNIX systems, the above is more easily written as perl -e 'print join("\n",@INC)."\n"', but that command will not work as is on a Windows command line.)
This list typically contains several directories; some containing O/S and platform specific names like i386_linux, split up into two main categories: those included with the standard Perl distribution and those that are intended for you to use specifically on your site (they're usually easy to tell apart; since the "site" specific directories are typically named site or site_perl or some variation). It's also common for @INC to include "." (a single dot) as the last entry, which indicates that Perl should search the directory you are currently in as a last resort before complaining that it can't find the module you requested. The dot entry is primarily for testing purposes, so you can test your module locally before deploying it system wide.
Obviously, then, in order for your script to "see" your module, it (the module) will typically be located in one of the directories listed in the @INC array. If the module is indeed to be used by everyone at your site, then a common choice is to place the module in the site or site_perl directory; so that everyone at your site will have access to it. Modules that are still in development or that you intend to use solely for your own purposes are better served in your own user directory, or a designated directory per your administrator (more on accessing those modules in a bit). Of course, if you have a system administrator, then you should definitely ask her where you should place the module; since she will no doubt have write access to the library directories blocked to all but administrators and more than likely already have a defined naming/location scheme for new local modules that need to be added.
For the time being, though, let's assume you are your system administrator and you need to decide where to place your module. Simply placing it in site_perl would work ok; but what if you did that every time you developed a new mod? The site_perl directory would easily become overloaded; and worse, it may become increasingly difficult to remember which module did what. To avoid this problem, it's possible--and quite common--to nest modules within sub-directories beneath those listed in @INC. When we nest a module in Perl, we simply place it in a lower level subdirectory beneath an existing directory in the @INC selections. For example, say we created a subdirectory called Hello beneath site_perl, and in our Hello directory, we placed SayHello.pm. We would then access the SayHello module in our Perl script like this:
And within the SayHello module itself, we would need to change the package declaration to package Hello::SayHello; (you'd also, in this case, need to change the reference in your print statement; we'll come back to that in a bit). We use the :: reference for system portability; Perl automatically assumes that where it sees the :: in the module names, it should insert the operating system's standard directory indicator (like a / for UNIX or a \ for Windows) and look in the resulting subdirectory for the module in question.
Recall on the previous page that we mentioned how you might separate your private modules from system modules via names with underscores. Now that we've introduced you to module nesting, another possibility is to place your modules in a subdirectory called Local, which is not used by the publicly available modules on CPAN. Then you could access your module via Local::SayHello, for example, without having to worry about some public module called SayHello accidentally overwriting yours in the future.
By the way, do not confuse this module nesting scheme with inheritance. Because the module is nested in a subdirectory below a higher level directory does not imply any automatic reliance of the lower level module on any module in the directory above it. Or, in other words, if we did place our module in the Hello directory, and the directory above our module happened to have a Hello.pm file within it, then loading our module via use Hello::SayHello; will not, in and of itself, provide us with access to the code in Hello.pm.
Perl provides another way to locate modules that may not be in any of the current @INC directories, and that's the use lib pragma. use lib allows you to specify a new directory that should be added to the @INC list for the duration of your application only, and therefore allows you to force your application to look in a directory of your choosing for your module. For example:
use lib qw(/myPerl/myModules/); use SayHello;
Again, be sure to check with your administrator before placing and using modules on your system.
What About require?
Another way to load a module in Perl script is to use the require command:
require allows you to fully specify any file name (it doesn't have to end in .pm) if you include the filename itself in quotes (or provide it as the result of an expression). For example, require "SayHello.pl";. When you use it to pull in a module file ending in .pm, however, you can drop the quotes and the .pm extension, as in the above example.
A bigger difference, between use and require, however, has to do with when the code in the module is actually loaded and executed. When you load a module using use, the module is loaded and executed at compile time, even before the remaining portion of the script is compiled. Additionally, the module's import routine is automatically executed (we'll discuss import more on the next page). This execution-on-loading feature is what enables modules--including the pragmas such as use strict or use lib--to alter how the remainder of the script is actually compiled (it also means you should be careful what kind of code that you include to be immediately executed within your module; since it will execute in the script that uses it even if the remainder of the script fails or if the author was testing the script with the -c command line option). require pulls in the code of the module at run-time; and if the file cannot be found generates a run time error. Because use provides the ability to affect the remaining compilation of the script, and because it allows for the importation of symbols from the module itself (more on that on page 4), it is the commonly used method for loading modules in Perl 5 scripts and later.
Recalling the fact that we cannot access variables and functions in another package directly (at least, not without some help, anyway), how do we actually access the variables and/or functions our now-available module contains? That's the prime topic of the next page of our primer.
Created: April 7, 2005
Revised: April 7, 2005