Previous Page
Next Page

10.3. Localizing Filehandles

If you have to use a package filehandle, localize it first.

Very occasionally, you simply have to use a package filehandle, rather than a lexical. For example, you might have existing code that relies on hard-wired bareword filehandle names.

In such cases, make sure that the symbol table entry involved is always referred to explicitly, with a leading asterisk. And, more importantly, always localize that typeglob within the smallest possible scope. For example:


    # Wrap the Bozo::get_data(  ) subroutine cleanly.
    # (Apparently this subroutine is hard-wired to only read from a filehandle
    #  named DATA::SRC. And it's used in hundreds of places throughout our
    #  buffoon-monitoring system, so we can't change it. At least we fired the
    #  clown that wrote this, didn't we???)...
sub get_fool_stats { my ($filename) = @_;
# Create a temporary version of the hardwired filehandle...
local *DATA::SRC;
# Open it to the specified file...
open *DATA::SRC, '<', $filename or croak "Can't open '$filename': $OS_ERROR";
# Call the legacy subroutine...
return Bozo::get_data( ); }

Applying local to the *DATA::SRC typeglob temporarily replaces that entry in the symbol table. Thereafter, the filehandle that is opened is stored in the temporary replacement typeglob, not in the original. And it's the temporary *DATA::SRC that Bozo::get_data( ) sees when it's called. Then, when the results of that call are returned, control passes back out of the body of get_fool_stats( ), at which point any localization within that scope is undone, and any pre-existing *DATA::SRC filehandle is restored.

Localization prevents most of the usual problems with bareword filehandles, because it ensures that the original *DATA::SRC is unaffected by the non-lexical open inside the call to get_fool_stats( ). It also guarantees that the filehandle is automatically closed at the end of the subroutine call. And using explicitly asterisked typeglobs instead of barewords avoids any confusion if there's also a DATA::SRC( ) subroutine.

Nonetheless, if you have a choice, lexical filehandles are still a better alternative. Unlike localized typeglobs, lexicals are strictly limited to the scope in which they are created. In contrast, localized package filehandles are available not only in their own scope, butas the previous example illustratesthey can also be seen in any deeper scope that is called from their own scope. So a localized package filehandle can still potentially be pre-empted (i.e., broken) by another careless open in some nested scope.

    Previous Page
    Next Page