Perl - 模块内文件的相对路径
Perl - Relative path of a file inside a module
我正在使用 Perl 建立一个网站。我按如下方式组织我的文件:
- /index.cgi
- /perl/modules/databaseFunctions.pm
- /perl/indexCheck.cgi
- /database/database.xml
在 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
正是,我以为你在找什么。
我正在使用 Perl 建立一个网站。我按如下方式组织我的文件:
- /index.cgi
- /perl/modules/databaseFunctions.pm
- /perl/indexCheck.cgi
- /database/database.xml
在 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
正是,我以为你在找什么。