【问题标题】:module creation using perl script [duplicate]使用 perl 脚本创建模块 [重复]
【发布时间】:2011-10-13 03:26:22
【问题描述】:

可能重复:
How do you create a Perl module?

我有读取 xml 文件并创建哈希表的脚本。它工作正常,但现在我需要为该代码创建模块,我可以在我的主函数中调用它。在我的主函数文件路径中作为输入,并将输出作为哈希。现在我需要为此代码创建模块。

#!/usr/bin/perl
use warnings;
use strict;
use XML::LibXML::Reader;

#Reading XML with a pull parser
my $file;
open( $file, 'formal.xml');
my $reader = XML::LibXML::Reader->new( IO => $file ) or die ("unable to open file");
my %nums;
while ($reader->nextElement( 'Data' ) ) {
    my $des = $reader->readOuterXml();
    $reader->nextElement( 'Number' ); 
    my $desnode = $reader->readInnerXml(); 
    $nums{$desnode}= $des;
    print( " NUMBER: $desnode\n" );
    print( " Datainfo: $des\n" );
}

如何为这段代码创建模块?

【问题讨论】:

    标签: perl


    【解决方案1】:

    您需要使用以下代码创建一个扩展名为 .pm 的文件,即“MyModule.pm”:

    package MyModule;
    use warnings;
    use strict;
    use XML::LibXML::Reader;
    
    sub mi_function_name {
       #Reading XML with a pull parser
       my $file;
       open( $file, 'formal.xml');
       my $reader = XML::LibXML::Reader->new( IO => $file ) or die ("unable to open file");
       my %nums;
       while ($reader->nextElement( 'Data' ) ) {
          my $des = $reader->readOuterXml();
          $reader->nextElement( 'Number' ); 
          my $desnode = $reader->readInnerXml(); 
          $nums{$desnode}= $des;
          print( " NUMBER: $desnode\n" );
          print( " Datainfo: $des\n" );
       }
    }
    
    1; #this is important
    

    并且在你要使用这个模块的文件中:

    use MyModule;
    #...
    MyModule::mi_function_name;
    

    这是一个非常简单和基本的模块用法,我推荐更好的教程讲座(http://www.perlmonks.org/?node_id=102347)以进一步了解这方面的知识

    【讨论】:

      【解决方案2】:

      看看Perl Documentation。包含的教程之一是perlmod。这提供了很多很好的信息。

      第一步:把你的程序变成一个子程序。这样,您就可以将其称为您的代码。我冒昧地这样做了:

      #!/usr/bin/perl
      use warnings;
      use strict;
      use Carp;
      use XML::LibXML::Reader;
      
      #Reading XML with a pull parser
      sub myFunction {
          my $fh = shift; #File Handle (should be opened before calling
      
          my $reader = XML::LibXML::Reader->new( IO => $fh )
              or croak ("unable to open file");
          my %nums;
          while ($reader->nextElement( 'Data' ) ) {
      
              my $des = $reader->readOuterXml();
      
              $reader->nextElement( 'Number' ); 
              my $desnode = $reader->readInnerXml(); 
      
              $nums{$desnode} = $des;
          }
          return %nums;
      }
      
      1;
      

      我做了一点改变。您注意到我不再打开文件。相反,您会将文件句柄传递给您的MyFunction 子例程。其次,它现在不是打印出$desnode$des,而是返回一个包含这些值的散列。您不希望子例程输出数据。您希望他们返回数据,并让您的程序决定如何处理这些信息。

      我还添加了use Carp; 行。 Carp 为您提供了两个功能(以及其他一些功能)。一个叫做carp,它是warning 的替代品,另一个叫做croak,它是die 的替代品。这两个函数的作用是报告调用您的函数的用户程序中的行号。这样,用户不会在您的模块中看到错误,而是在他们的程序中看到错误。

      我还在您的程序底部添加了1; 行。加载模块时,如果加载时返回零,则加载失败。因此,您的最后一条语句应该返回一个非零值。 1; 保证它。


      现在我们有了一个可以返回的子例程,让我们把你的程序变成一个模块。

      要创建一个模块,您只需在程序顶部输入package <moduleName>。并且,还要确保最后一条语句以非零值执行。传统只是将1; 作为程序的最后一行。默认情况下,模块名称以 .pm 后缀结尾。模块名称可以在名称中包含由双冒号分隔的组件。例如File::Basename。在这种情况下,模块Basename.pm 位于@INC 目录列表中的某个目录File 中(默认情况下包括当前目录)。

      package 命令只是创建一个单独的命名空间,因此您的包变量和函数不会与使用您的包的程序中的变量和函数的名称发生冲突。

      如果您使用面向对象的接口,则没有理由需要导出任何内容。使用您的模块的程序将简单地使用面向对象的语法。如果您的模块是基于函数的,您可能希望将函数名称导出到主程序中。

      例如,我们以File::Basename 为例。该模块将函数basenamedirname 导入到您的程序中。这允许您这样做:

      my $directoryName = dirname $fileName;
      

      不必这样做:

      my $direcotryName = File::Basename::dirname $fileName;
      

      要导出函数,请确保您的模块使用 Exporter 模块,然后设置 package 变量 @EXPORT_OK@EXPORT 以包含列表您允许在用户程序中导出的功能。不同的是,如果你说@EXPORT_OK,函数将被导出,但用户必须请求每一个。如果你使用@EXPORT,所有这些函数都会被自动导出。

      以您的程序为基础,您的模块将被称为Mypackage.pm,如下所示:

      #!/usr/bin/perl
      
      package Mymodule;
      
      use warnings;
      use strict;
      use Exporter qw(import);
      use Carp;
      use XML::LibXML::Reader;
      
      our @EXPORT_OK(myFunction);
      
      #Reading XML with a pull parser
      sub MyFunction {
          my $fh = shift; #File Handle (should be opened before calling
      
          my $reader = XML::LibXML::Reader->new( IO => $fh )
              or die ("unable to open file");
          my %nums;
          while ($reader->nextElement( 'Data' ) ) {
      
              my $des = $reader->readOuterXml();
      
              $reader->nextElement( 'Number' ); 
              my $desnode = $reader->readInnerXml(); 
      
              $nums{$desnode}= $des;
          }
          return %nums;
      }
      
      1;
      

      最重要的是使用:

      • package Mypackage
      • use Exporter qw(import)
      • our @EXPORT_OK qw(myFunction);

      package 函数设置了一个独立的名称空间,因此您的变量和函数名称不会被用户程序覆盖(或被覆盖)。

      use Exporter 表示您的程序正在使用Exporter 模块的import 函数。这允许您将变量和函数导入用户程序的主命名空间。这样,用户可以简单地将您的函数称为mi_function_name 而不是Mypackage::my_function_name。理论上,您不必导出任何东西,而较新的模块也不必。这些模块完全是面向对象的,或者只是不想为命名空间问题而烦恼。

      @EXPORT_OK 数组表示您要导出的内容。这比@EXPORT 更受欢迎。使用@EXPORT_OK,开发人员必须指定他想将哪些函数导入到他们的程序中。使用@EXPORT,这是自动完成的。

      在使用您的模块的程序中,您需要这样做:

      use Mypackage qw(myFunction);
      

      现在,您在程序中所要做的就是

      my %returnedHash = myFunction($fh);
      

      现在,Perl 不断发展,而我从未接受过任何正式培训。我只是阅读文档并查看各种示例并希望我正确理解它们。所以,如果有人可能会说我做错了什么,他们可能是正确的。我也没有测试任何代码。当我把它变成一个子程序时,我可能在你的程序中搞砸了。

      但是,要点应该是正确的:您需要将代码变成可调用的子例程,以返回您需要的信息。然后,你可以把它变成一个模块。做起来并不难。

      【讨论】:

      • 非常感谢我通过阅读您提供的代码和数据解决了我的问题,这对我有很大帮助。@david。
      猜你喜欢
      • 2021-02-13
      • 2011-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多