我正在为其他人编写程序以供使用。其中一个设计规范是使用Term :: ReadLine :: Gnu Perl库。大多数用户都没有安装,我想在程序运行时安装它。
因此,当用户启动程序时,他们没有安装库。我的程序将在他们使用OS包管理器使用程序时为他们安装。
我正在检查模块
require Term::ReadLine;
my $Readline_Support = 1;
eval { require Term::ReadLine::Gnu }
or $Readline_Support = 0;
我使用$ Readline_Support变量重定向终端,使用历史文件等。
$OUT = $TERMINAL->OUT if $readline_installed;
if ($readline_installed)
{
# save every answer and default, good or not, to the history file
$TERMINAL->add_history($Ans);
$TERMINAL->append_history(1, HIST_FILE);
}
不幸的是,当我尝试使用历史文件时出现此错误:
无法在./msi.pl第618行第2行通过包“Term :: ReadLine :: Stub”找到对象方法“using_history”。
第618行是
$TERMINAL->using_history();
第一次使用$ TERMINAL对象。
是否有人在脚本运行时安装Perl模块,然后在同一个脚本中使用模块?
好的...感谢Andy,如果没有安装模块,那么
# I removed the require Term::ReadLine; here
my $Readline_Support = 1;
eval { require Term::ReadLine::Gnu }
or $Readline_Support = 0;
下面的代码
if ($readline_installed)
{
# Required for the dynamic loading of Term::ReadLine::Gnu
require Term::ReadLine;
$TERMINAL = Term::ReadLine->new ('ProgramName')
if $Interactive or $Brief
}
然而,现在,对已安装mod的检查总是失败,我认为是因为
require Term::ReadLine::Gnu;
需要
require Term::ReadLine;
在代码的早期,就像旧的
一样 require Term::ReadLine;
my $Readline_Support = 1;
eval { require Term::ReadLine::Gnu }
or $Readline_Support = 0;
答案 0 :(得分:2)
大多数用户都没有安装,我想在程序运行时安装它。
你在这里游泳。没有其他人这样做,安装后更换系统也会让我认识的大多数系统管理员感到不安。
只需声明依赖项,因此在安装程序时,还会安装T :: R :: G.我链接到How do I create a build for a legacy system?中的相关文档。
工具链已经为您提供了所有必要的功能,让每个参与其中的人都可以轻松学习。
答案 1 :(得分:1)
您可以从“cpan”命令本身学习。 cpan可以自己安装(升级)并重新加载所有使用过的模块。这应该是一个很好的学习起点。
答案 2 :(得分:0)
我在Term::ReadLine
的代码中看到,它确定在加载时将使用哪个实现,而不是在调用new
时。所以我建议采用以下顺序:
Term::ReadLine::Gnu
的可用性,就像您当前一样,但在加载任何ReadLine
模块之前Term::ReadLine::Gnu
(如果不存在)require Term::ReadLine
Term::ReadLine->new
事情变得更加复杂,因为Term::ReadLine::Gnu
在尝试使用use
或require
直接加载时会引发错误,因此直截了当的eval
测试失败,即使它是安装。解决这个问题的一种方法是解析$@
,但我不喜欢解析诊断消息,因为它们可能会随着时间的推移而发生变化。从%INC
删除也不是很好,但只要直接加载Term::ReadLine::Gnu
的错误不会消失,就应该有效。
my $readline_installed = 1;
unless (eval { require Term::ReadLine::Gnu; }) {
# Term::ReadLine::Gnu throws an error that it can't be loaded directly,
# even when it's installed.
$readline_installed = exists ($INC{"Term/ReadLine/Gnu.pm"});
# Needed so that it will be reloaded after installation
delete $INC{"Term/ReadLine/Gnu.pm"};
}
unless ($readline_installed) {
print "Installing Term::ReadLine::Gnu\n";
# ...
}
require Term::ReadLine;
my $term = Term::ReadLine->new ("app");
$term->addhistory ("blah");
print $term->readline ("> "), "\n";