分享好友 编程语言首页 频道列表

Perl 之 use(), require(), do(), %INC and @INC

perl  2023-02-09 10:260

use(), require(), do(), %INC and @INC Explained


Perl 之 use(), require(), do(), %INC and @INC 

The @INC array

@INC is a special Perl variable which is the equivalent of the shell's PATH variable. Whereas PATH contains a list of directories to search for executables, @INC contains a list of directories from which Perl modules and libraries can be loaded.

When you use(), require() or do() a filename or a module, Perl gets a list of directories from the @INC variable and searches them for the file it was requested to load. If the file that you want to load is not located in one of the listed directories, you have to tell Perl where to find the file. You can either provide a path relative to one of the directories in @INC, or you can provide the full path to the file.



Perl 之 use(), require(), do(), %INC and @INC 

The %INC hash

%INC is another special Perl variable that is used to cache the names of the files and the modules that were successfully loaded and compiled by use(), require() or do() statements. Before attempting to load a file or a module with use() or require(), Perl checks whether it's already in the %INC hash. If it's there, the loading and therefore the compilation are not performed at all. Otherwise the file is loaded into memory and an attempt is made to compile it. do() does unconditional loading--no lookup in the %INC hash is made.

If the file is successfully loaded and compiled, a new key-value pair is added to %INC. The key is the name of the file or module as it was passed to the one of the three functions we have just mentioned, and if it was found in any of the @INC directories except "." the value is the full path to it in the file system.

The following examples will make it easier to understand the logic.

First, let's see what are the contents of @INC on my system:

  % perl -e 'print join "\n", @INC'
  /usr/lib/perl5/5.00503/i386-linux
  /usr/lib/perl5/5.00503
  /usr/lib/perl5/site_perl/5.005/i386-linux
  /usr/lib/perl5/site_perl/5.005
  .

Notice the . (current directory) is the last directory in the list.

Now let's load the module strict.pm and see the contents of %INC:

  % perl -e 'use strict; print map {"$_ => $INC{$_}\n"} keys %INC'
  
  strict.pm => /usr/lib/perl5/5.00503/strict.pm

Since strict.pm was found in /usr/lib/perl5/5.00503/ directory and /usr/lib/perl5/5.00503/ is a part of @INC%INC includes the full path as the value for the key strict.pm.

Now let's create the simplest module in /tmp/test.pm:

  test.pm
  -------
  1;

It does nothing, but returns a true value when loaded. Now let's load it in different ways:

  % cd /tmp
  % perl -e 'use test; print map {"$_ => $INC{$_}\n"} keys %INC'
  
  test.pm => test.pm

Since the file was found relative to . (the current directory), the relative path is inserted as the value. If we alter @INC, by adding /tmp to the end:

  % cd /tmp
  % perl -e 'BEGIN{push @INC, "/tmp"} use test; \
  print map {"$_ => $INC{$_}\n"} keys %INC'
  
  test.pm => test.pm

Here we still get the relative path, since the module was found first relative to ".". The directory /tmp was placed after . in the list. If we execute the same code from a different directory, the "." directory won't match,

  % cd /
  % perl -e 'BEGIN{push @INC, "/tmp"} use test; \
  print map {"$_ => $INC{$_}\n"} keys %INC'
  
  test.pm => /tmp/test.pm

so we get the full path. We can also prepend the path with unshift(), so it will be used for matching before "." and therefore we will get the full path as well:

  % cd /tmp
  % perl -e 'BEGIN{unshift @INC, "/tmp"} use test; \
  print map {"$_ => $INC{$_}\n"} keys %INC'
  
  test.pm => /tmp/test.pm

The code:

  BEGIN{unshift @INC, "/tmp"}

can be replaced with the more elegant:

  use lib "/tmp";

Which is almost equivalent to our BEGIN block and is the recommended approach.

These approaches to modifying @INC can be labor intensive, since if you want to move the script around in the file-system you have to modify the path. This can be painful, for example, when you move your scripts from development to a production server.

There is a module called FindBin which solves this problem in the plain Perl world, but unfortunately up untill perl 5.9.1 it won't work under mod_perl, since it's a module and as any module it's loaded only once. So the first script using it will have all the settings correct, but the rest of the scripts will not if located in a different directory from the first. Perl 5.9.1 provides a new function FindBin::again which will do the right thing. Also the CPAN module FindBin::Real provides a working alternative working under mod_perl.

For the sake of completeness, I'll present the FindBin module anyway.

If you use this module, you don't need to write a hard coded path. The following snippet does all the work for you (the file is /tmp/load.pl):

  load.pl
  -------
  #!/usr/bin/perl
  
  use FindBin ();
  use lib "$FindBin::Bin";
  use test;
  print "test.pm => $INC{'test.pm'}\n";

In the above example $FindBin::Bin is equal to /tmp. If we move the script somewhere else... e.g. /tmp/new_dir in the code above $FindBin::Bin equals /tmp/new_dir.

  % /tmp/load.pl
  
  test.pm => /tmp/test.pm

This is just like use lib except that no hard coded path is required.

You can use this workaround to make it work under mod_perl.

  do 'FindBin.pm';
  unshift @INC, "$FindBin::Bin";
  require test;
  #maybe test::import( ... ) here if need to import stuff

This has a slight overhead because it will load from disk and recompile the FindBin module on each request. So it may not be worth it.



Perl 之 use(), require(), do(), %INC and @INC 

Modules, Libraries and Program Files

Before we proceed, let's define what we mean by modulelibrary and program file.

  • Libraries

    These are files which contain Perl subroutines and other code.

    When these are used to break up a large program into manageable chunks they don't generally include a package declaration; when they are used as subroutine libraries they often do have a package declaration.

    Their last statement returns true, a simple 1; statement ensures that.

    They can be named in any way desired, but generally their extension is .pl.

    Examples:

      config.pl
      ----------
      # No package so defaults to main::
      $dir = "/home/httpd/cgi-bin";
      $cgi = "/cgi-bin";
      1;
    
      mysubs.pl
      ----------
      # No package so defaults to main::
      sub print_header{
        print "Content-type: text/plain\r\n\r\n";
      }
      1;
    
      web.pl
      ------------
      package web ;
      # Call like this: web::print_with_class('loud',"Don't shout!");
      sub print_with_class{
        my ( $class, $text ) = @_ ;
        print qq{<span class="$class">$text</span>};
      }
      1;
  • Modules

    A file which contains perl subroutines and other code.

    It generally declares a package name at the beginning of it.

    Modules are generally used either as function libraries (which .pl files are still but less commonly used for), or as object libraries where a module is used to define a class and its methods.

    Its last statement returns true.

    The naming convention requires it to have a .pm extension.

    Example:

      MyModule.pm
      -----------
      package My::Module;
      $My::Module::VERSION = 0.01;
      
      sub new{ return bless {}, shift;}
      END { print "Quitting\n"}
      1;
  • Program Files

    Many Perl programs exist as a single file. Under Linux and other Unix-like operating systems the file often has no suffix since the operating system can determine that it is a perl script from the first line (shebang line) or if it's Apache that executes the code, there is a variety of ways to tell how and when the file should be executed. Under Windows a suffix is normally used, for example .pl or .plx.

    The program file will normally require() any libraries and use() any modules it requires for execution.

    It will contain Perl code but won't usually have any package names.

    Its last statement may return anything or nothing.



Perl 之 use(), require(), do(), %INC and @INC 

require()

require() reads a file containing Perl code and compiles it. Before attempting to load the file it looks up the argument in %INC to see whether it has already been loaded. If it has, require() just returns without doing a thing. Otherwise an attempt will be made to load and compile the file.

require() has to find the file it has to load. If the argument is a full path to the file, it just tries to read it. For example:

  require "/home/httpd/perl/mylibs.pl";

If the path is relative, require() will attempt to search for the file in all the directories listed in @INC. For example:

  require "mylibs.pl";

If there is more than one occurrence of the file with the same name in the directories listed in @INC the first occurrence will be used.

The file must return TRUE as the last statement to indicate successful execution of any initialization code. Since you never know what changes the file will go through in the future, you cannot be sure that the last statement will always return TRUE. That's why the suggestion is to put "1;" at the end of file.

Although you should use the real filename for most files, if the file is a module, you may use the following convention instead:

  require My::Module;

This is equal to:

  require "My/Module.pm";

If require() fails to load the file, either because it couldn't find the file in question or the code failed to compile, or it didn't return TRUE, then the program would die(). To prevent this the require() statement can be enclosed into an eval() exception-handling block, as in this example:

  require.pl
  ----------
  #!/usr/bin/perl -w
  
  eval { require "/file/that/does/not/exists"};
  if ($@) {
    print "Failed to load, because : $@"
  }
  print "\nHello\n";

When we execute the program:

  % ./require.pl
  
  Failed to load, because : Can't locate /file/that/does/not/exists in
  @INC (@INC contains: /usr/lib/perl5/5.00503/i386-linux
  /usr/lib/perl5/5.00503 /usr/lib/perl5/site_perl/5.005/i386-linux
  /usr/lib/perl5/site_perl/5.005 .) at require.pl line 3.
  
  Hello

We see that the program didn't die(), because Hello was printed. This trick is useful when you want to check whether a user has some module installed, but if she hasn't it's not critical, perhaps the program can run without this module with reduced functionality.

If we remove the eval() part and try again:

  require.pl
  ----------
  #!/usr/bin/perl -w
  
  require "/file/that/does/not/exists";
  print "\nHello\n";

  % ./require1.pl
  
  Can't locate /file/that/does/not/exists in @INC (@INC contains:
  /usr/lib/perl5/5.00503/i386-linux /usr/lib/perl5/5.00503
  /usr/lib/perl5/site_perl/5.005/i386-linux
  /usr/lib/perl5/site_perl/5.005 .) at require1.pl line 3.

The program just die()s in the last example, which is what you want in most cases.

For more information refer to the perlfunc manpage.



Perl 之 use(), require(), do(), %INC and @INC 

use()

use(), just like require(), loads and compiles files containing Perl code, but it works with modules only and is executed at compile time.

The only way to pass a module to load is by its module name and not its filename. If the module is located in MyCode.pm, the correct way to use() it is:

  use MyCode

and not:

  use "MyCode.pm"

use() translates the passed argument into a file name replacing :: with the operating system's path separator (normally /) and appending .pm at the end. So My::Module becomes My/Module.pm.

use() is exactly equivalent to:

 BEGIN { require Module; Module->import(LIST); }

Internally it calls require() to do the loading and compilation chores. When require() finishes its job, import() is called unless () is the second argument. The following pairs are equivalent:

  use MyModule;
  BEGIN {require MyModule; MyModule->import; }
  
  use MyModule qw(foo bar);
  BEGIN {require MyModule; MyModule->import("foo","bar"); }
  
  use MyModule ();
  BEGIN {require MyModule; }

The first pair exports the default tags. This happens if the module sets @EXPORT to a list of tags to be exported by default. The module's manpage normally describes what tags are exported by default.

The second pair exports only the tags passed as arguments.

The third pair describes the case where the caller does not want any symbols to be imported.

import() is not a builtin function, it's just an ordinary static method call into the "MyModule" package to tell the module to import the list of features back into the current package. See the Exporter manpage for more information.

When you write your own modules, always remember that it's better to use @EXPORT_OK instead of @EXPORT, since the former doesn't export symbols unless it was asked to. Exports pollute the namespace of the module user. Also avoid short or common symbol names to reduce the risk of name ***es.

When functions and variables aren't exported you can still access them using their full names, like $My::Module::bar or $My::Module::foo(). By convention you can use a leading underscore on names to informally indicate that they are internal and not for public use.

There's a corresponding "no" command that un-imports symbols imported by use, i.e., it calls Module->unimport(LIST) instead of import().



Perl 之 use(), require(), do(), %INC and @INC 

do()

While do() behaves almost identically to require(), it reloads the file unconditionally. It doesn't check %INC to see whether the file was already loaded.

If do() cannot read the file, it returns undef and sets $! to report the error. If do() can read the file but cannot compile it, it returns undef and puts an error message in $@. If the file is successfully compiled, do() returns the value of the last expression evaluated.

 

完!

查看更多关于【perl】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
Linux下安装Perl和Perl的DBI模块
今天在虚拟机测试shell脚本的时候,有些命令使用不了。比如说 mysqlhotcopy ,它提示Perl的版本太低。我用的 RedHat9 的Perl才5.8.0版本。。。(2002年以前的)严重过时。所以重新安装了新版本的 Perl,过程记录如下: 1、在官方网站下载新版本的源码包:http:

0评论2023-03-16464

Perl 与Form
说明事项: 這個範例用來說明如何經由網頁上的HTML form 表單元件來呼叫伺服器端的perl 程式。这个范例用来说明如何经由网页上的HTML form 表单元件来呼叫伺服器端的perl 程式。首先在網頁上設計表單元件,這個範例是設計一個按鈕,其原始碼如下:首先在网页

0评论2023-02-10545

Perl学习 perl培训
http://www.sun126.com/perl5/perl5-1.htm翻译: flamephoenix 第一章 概述一、Perl是什么?二、Perl在哪里?三、运行四、注释一、Perl是什么?  Perl是Practical Extraction and Report Language的缩写,它是由Larry Wall设计的,并由他不断更新和维护,用

0评论2023-02-10506

- calm_水手">Perl中的箭头符-> - calm_水手
Perl中的箭头符-2012-05-21 17:14 calm_水手 阅读(623) 评论(0) 编辑 收藏 举报  有两种用法,都和解引用有关。第一种用法,就是解引用。根据 - 后面跟的符号的不同,解不同类型的引用,-[] 表示解数组引用,-{} 表示解散列引用,-() 表示解子程序引

0评论2023-02-09731

perl脚本语言学习 perl脚本调用perl脚本
来公司的第二个星期便看了一下perl语言,发现掌握一门脚本语言还是非常有用的。到现在为止已经入职两个月,用perl脚本做了这些活:1. 修改了公司的一个爬取网页源代码的脚本2. 改进了一个出特征库的脚本,根据svn status的状态,来优化,将只需要添加的DB的数

0评论2023-02-09317

Perl模块的安装方法 perl 安装模块
1. 下载离线安装包 *.tar.gz的形式解包后,#perl Makefile.PL#make#make install2. 在联网的情况下,通过CPAN安装# perl -MCPAN -e shellcpan install PAR::Packer 

0评论2023-02-09909

Perl像C一样强大,像awk、sed等脚本描述语言一样方便。
Perl是由Larry Wall设计的,并由他不断更新和维护的编程语言。Perl具有高级语言(如C)的强大能力和灵活性。事实上,你将看到,它的许多特性是从C语言中借用来的。Perl与 脚本语言一样,Perl不需要编译器和链接器来运行代码,你要做的只是写出程序并告诉Perl

0评论2023-02-09370

27-Perl 进程管理
1.Perl 进程管理Perl 中你可以以不同的方法来创建进程。本教程将讨论一些进程的管理方法。你可以使用特殊变量 $$ 或 $PROCESS_ID 来获取进程 ID。%ENV 哈希存放了父进程,也就是shell中的环境变量,在Perl中可以修改这些变量。exit() 通常用于退出子进程,主

0评论2023-02-09436

在perl中简单的正则匹配 正则匹配或的使用
(一)、在perl中关于元字符的匹配元字符代表含义点号( .)匹配处换行符以外的任何单字符星号(*)匹配前面的内容零次或多次反斜线屏蔽元字符的特殊含义。\\代表\,\.匹配点号.*匹配所有的字符串加号(+)匹配前一个条目一次以上问号(?)表示前面一个条目可

0评论2023-02-09908

Perl WEB 开发之 Template
由于工作需要, 最近开始使用Perl来作为服务器脚本来处理Web 请求。系统采用的Template 来做Web page 的模板,用来简化繁琐但并不困难的HTML标签的编写。Question 1: Template Toolkit 是啥?Template Toolkit是一组Perl Module的集合, 它实现了一种快速的

0评论2023-02-09418

Perl到底是什么意思? perpol意思
学习perl也有一段时间了,如果连perl是什么意思都不知道,那就太汗颜了,听好啦!perl == Practical Exstraction and Report Language,中文叫做实用抽取和报表语言。

0评论2023-02-09437

perl-cgi-form2
代码:         #!/usr/local/bin/perl        use CGI ':standard';        print header;        print start_html("Example CGI.pm Form");        print "h1 Example CGI.pm Form/h1\n";      

0评论2023-02-09501

Perl实战(一) perl进阶
在Perl中,我们可以通过uc,lc,\U,\L来修改变量的值。其中uc,\U可以将变量中的字母全部转换为大写。              lc,\L可以将变量中的字母全部转换为小写。              $big = "\U$var";       $big = uc($var);  

0评论2023-02-09685

Perl多线程(2):数据共享和线程安全 多线程epoll
线程数据共享在介绍Perl解释器线程的时候一直强调,Perl解释器线程在被创建出来的时候,将从父线程中拷贝数据到子线程中,使得数据是线程私有的,并且数据是线程隔离的。如果真的想要在线程间共享数据,需要显式使用threads::shared模块来扩展threads模块的功

0评论2023-02-09683

Linux下安装与使用本地的perl模块 centos安装perl
在使用Linux或是unix时,perl是一个非常有用的脚本的语言。关于perl的模块安装,网上也有很多介绍,一方面可以通过不同套件自带的软件安装工具安装,一方面可以通过cpan安装,再者就是可以直接编译源代码。 这样,对于拥有root权限的用户来说,没有任何问题

0评论2023-02-09497

Perl_Tkx_Canvas绘图功能函数介绍
1.画画布:     $canvas = $mw-new_tk__canvas;2.画线:         $canvas-create_line(10,10,200,50,-fill=”red”,-width=3);配置item参数:       $canvas-itemconfigure($id, -fill = "blue", -width = 2);3.画椭圆         “ova

0评论2023-02-09658

perl: warning: Falling back to the standard locale ("C").
/********************************************************************************** *perl: warning: Falling back to the standard locale ("C"). * 说明: * 使用debootstrap的时候,遇到这个问题,记录解决方法。 **2017-2-18 深圳 南山平山村 曾剑锋

0评论2023-02-09574

Perl操作Mysql数据库 perl操作excel
一. 安装DBI模块步骤1:从TOOLS栏目中下载DBI.zip,下载完后用winzip解开到一个temp目录,共有三个文件:ReadmeDBI.ppdDBI.tar.gz步骤2: 在DOS窗口下,temp目录中运行下面的DOS命令:ppm install DBI.ppd 如果提示无效命令,可在perl/bin目录下运行 二. 安装DBD

0评论2023-02-09348

更多推荐