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

Perl - Relative path of a file inside a module

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

databaseFunctions.pm 中,我有一个函数 X() 可以在 database.xml 上读写。在 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 或 /perl/indexCheck.cgi 中调用 X() 时,数据库的相对路径不同,但我不知道如何设置适用于 index.cgi 和 /perl/indexCheck.cgi.

的路径

我认为问题归结为 "How to find out the path of the current script (*.pl)?" 并且 "How to find out the path of the current module (*.pm)?".

脚本

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

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

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

该模块是核心分发的一部分,即无需进一步安装。

模块

FindBin 可能无法从模块内部安全地使用,因为这取决于谁(脚本或模块)创建了第一个 use FindBin;。 所以如果你不想关心顺序,不要use FindBin;在模块中,只在脚本中。

对于模块,有一些技巧。使用 perl 函数 caller()。 根据调用的上下文,它 returns 实际调用它的文件的 $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/modules/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/database.xml:

called from index.cgi
called from indexCheck.cgi

正是,我以为你在找什么。