使用lib相对于模块的路径 [英] use lib for paths relative to a module

查看:106
本文介绍了使用lib相对于模块的路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在找出use lib的相对路径时遇到问题.这是我要执行的操作的示例:

I'm having issues figuring out relative paths for use lib. Here is an example of what I am trying to do:

我有一个目录调用foo,其中包含一个名为myscript.pl的脚本. myscript.pl使用位于bar子目录中的名为Mod1.pm的模块,因此在myscript.pl的顶部放置以下行:

I have a directory call foo, which contains a script named myscript.pl. myscript.pl uses a module named Mod1.pm located in a subdirectory called bar, so at the top of myscript.pl I put the lines:

    use lib 'bar';
    use Mod1;

这很好,直到我希望Mod1.pm使用另一个模块foo/bar/asdf/Mod2.pm.如果将use lib 'asdf'放在Mod1.pm的顶部,则此操作将不起作用,因为它相对于我正在运行myscript.pl的目录进行搜索.因此,我进行了一些搜索,找到了FindBin,然后尝试将这些行添加到Mod1.pm:

This works fine, until I want Mod1.pm to use another module, foo/bar/asdf/Mod2.pm. If I put a use lib 'asdf' at the top of Mod1.pm this won't work because it searches relative to the directory I'm running myscript.pl from. So I did some searching and found FindBin, and tried adding these lines to Mod1.pm:

    use FindBin;
    use lib "$FindBin::Bin/asdf";

这也不起作用,因为FindBin找到了我正在运行的脚本(myscript.pl)所在的目录,而不是使用FindBin的文件(在本例中为Mod1.pm).所以我的问题是,有没有一种方法可以相对于Mod1.pm所在的位置进行搜索,以便无论使用Mod1.pm的脚本位于何处都可以找到Mod2.pm?

This didn't work either, because FindBin finds the directory that the script I am running (myscript.pl) is located in, not the file that uses FindBin (in this case Mod1.pm). So my question is, is there a way to search relative to where Mod1.pm is located, so that it can find Mod2.pm no matter where the script that uses Mod1.pm is located?

对我的情况的进一步解释,以解决您的一些评论:

Further explanation of my situation to address some of your comments:

我正在处理存储库中的代码,所有CPAN库都需要安装在存储库中的目录中.这意味着use lib不能有任何绝对路径.对于我的项目,有一个中央模块"Mod1.pm",其中use包含了很多CPAN模块,这些模块位于存储库中的各个目录中.所有use lib语句的格式均为use lib '../../foo/bar/asdf',因此可以在运行脚本的位置找到它们,但这限制了您可以在运行Mod1.pm的脚本的位置进行尝试.避免.另一个烦人的副作用是,我不能仅perl -c Mod1.pm来确保对Mod1.pm所做的任何编辑都是合理的,除非我在正确的位置运行它,否则该位置通常不是Mod1.pm所在的位置.哦,加入已经有凌乱代码的项目带来的乐趣...另一个令人讨厌的副作用是,我不能使用任何一个您建议用来解决问题的CPAN模块,因为我仍然需要一种方法找到那些.

I'm working on code in a repository, and all CPAN libraries need to be installed in a directory in the repository. That means that the use libs can't have any absolute paths. For my project there is a central module "Mod1.pm" which usees quite a few CPAN modules that are located in various directories in the repository. All of the use lib statements are of the form use lib '../../foo/bar/asdf' so that they can be found relative to wherever you're running the script from, but this restricts where you can run scripts that use Mod1.pm, which I'm trying to avoid. Another annoying side effect is that I can't just perl -c Mod1.pm to make sure any edits I make to Mod1.pm are sane, unless I'm running it in the right place, which conveniently isn't where Mod1.pm is located. Oh the joys of joining a project that already has messy code in place... Another nasty side effect is that I can't use any CPAN modules that any of you are suggesting to fix my problems, because I'd still need a way to find those.

推荐答案

通常,您希望您的主程序自行查找其所有库,在这种情况下,您应该按照Alec Chen的回答进行操作.

Usually you want your main program to find all its libraries on its own, in which case you should do as Alec Chen answered.

在某些情况下,例如查找插件,您希望一个库查找相对于其位置的其他库.

In some situations, such as finding plug ins, you want a library to find other libraries relative to its location.

您可以使用 __FILE__ 进行操作,该文件包含当前文件的位置源代码.

You can do this using __FILE__ which contains the location of the current file of source code.

package Mod1;

use strict;
use warnings;

use File::Basename;

# Must put this in a BEGIN block so it happens at "compile time" while the
# "use"s are being executed.  But the "my" declaration must happen outside
# the BEGIN block else it can't be seen.
my $module_dir;
BEGIN { $module_dir = dirname(__FILE__); }

use lib $module_dir;

use Mod2;

上面编写的有趣方式是因为每个Perl文件都有两个(或更多)执行阶段. 编译时间"和运行时间". use语句在编译时发生.为了use lib $module_dir,我们必须在编译时使用BEGIN块设置$module_dir.使困惑?有更简单的方法...

The funny way that's written above is because each Perl file has two (or more) stages of execution. "Compile time" and "run time". use statements happen at compile time. In order to use lib $module_dir, we must set $module_dir at compile time with a BEGIN block. Confused? There's easier ways...

对于模块来说,全局更改@INC是一种不好的形式.加载模块不应更改程序的全局状态(除非这是其功能的一部分).您应该将其本地化.

It is bad form for a module to alter @INC globally. Loading a module should not change the global state of the program (unless that's part of its functionality). You would instead localize it.

package Mod1;

use strict;
use warnings;

use File::Basename;
my $module_dir = dirname(__FILE__);

{
    local @INC;
    push @INC, $module_dir;
    require Mod2;
}

但是直接将其作为文件可能更简单.

But its probably simpler to just require it directly as a file.

package Mod1;

use strict;
use warnings;

use File::Basename;
use File::Spec;
my $module_dir = dirname(__FILE__);
require File::Spec->catfile($module_dir, "Mod2.pm");

而且,这是Perl,有一些模块可以处理具有插件的 Module :: Pluggable 非常受欢迎.

And, this being Perl, there are modules to handle having plugins, Module::Pluggable being very popular.

这篇关于使用lib相对于模块的路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆