Perl - 模块内文件的相对路径

时间:2016-01-30 16:52:46

标签: perl relative-path perl-module

我正在使用Perl构建一个网站。我按如下方式组织了我的文件:

  • /index.cgi
  • /perl/modules/databaseFunctions.pm
  • /perl/indexCheck.cgi
  • /database/database.xml

databaseFunctions.pm 里面我有一个在database.xml上读写的函数X()。在X()中,我指定了数据库的相对路径如下:

sub X{
    my $db_path='../../database/database.xml';
    my $parser=XML::LibXML->new();
    my $doc=$parser->parse_file($db_path);
    ....
    ....
 }

问题在于:
我必须从index.cgi和indexCheck.cgi调用X()但是我得到一个错误,出现以下错误:

Could not create file parser context for file "../../database/database.xml": No such file or directory at perl/modules/databaseFunctions.pm line 21.

我认为问题在于,当我在index.cgi中调用X()或在/perl/indexCheck.cgi内调用数据库的相对路径时,我不知道如何设置有效的路径对于index.cgi和/perl/indexCheck.cgi。

1 个答案:

答案 0 :(得分:2)

我认为问题归结为"如何找出当前脚本(* .pl)的路径?"和 "如何找出当前模块的路径(* .pm)?"。

脚本

对于脚本,有一个非常方便的模块FindBin,它为当前脚本的名称和路径提供了4个变量。 符号链接是否已解决。通常$FindBin::Bin是您正在寻找的。它是当前脚本的路径。 我经常使用它来增强@INC路径,以便我的脚本找到其他(自己的)模块,如下所示:

use FindBin;
use lib "$FindBin::Bin/my_mod_path";
use MyModule;

在这种情况下,在当前脚本路径下方的目录MyModule.pm中搜索my_mod_path。非常方便。

该模块是核心发行版的一部分,即不需要进一步安装。

模块

FindBin可能无法安全地从模块内部使用,因为它取决于谁(脚本或模块)创建第一个use FindBin;。 因此,如果您不想关心订单,请不要在模块中use FindBin;,只能在脚本中使用。

对于模块,有一些技巧。使用perl函数caller()。 根据调用的上下文,它返回实际调用它的文件的$filename

因此,在模块中,您可以安全地使用以下内容来获取模块的路径:

use File::Basename;
my $path_of_this_module = File::Basename::dirname( eval { ( caller() )[1] } );

根据该路径,您可以相对于它进行导航,以便找到您需要的其他文件,例如"$path_of_this_module/../.."等等。

修改

的index.cgi:

#!/usr/bin/env perl

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/perl/modules";
use databaseFunctions;

databaseFunctions::X( "called from index.cgi\n" );

的perl / indexCheck.cgi:

#!/usr/bin/env perl

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/modules";
use databaseFunctions;

databaseFunctions::X( "called from indexCheck.cgi\n" );

的perl /模块/ databaseFunctions.pm:

package databaseFunctions;

use File::Basename;

my $path_of_this_module = File::Basename::dirname( eval { ( caller() )[1] } );

sub X {
    my $arg = shift;

    my $db_path="$path_of_this_module/../../database/database.xml";

    open(my $fh, '>>', $db_path) or die "cannot open $db_path: $!\n";
    print $fh $arg;
    close($fh);
}

1;

当我现在调用./index.cgi然后调用./perl/indexCheck.cgi时,我得到以下内容:

数据库/ database.xml:

called from index.cgi
called from indexCheck.cgi

确切地说,我认为你在寻找。