簡體   English   中英

在運行Perl腳本並在腳本中使用模塊時安裝Term :: ReadLine :: Gnu

[英]Installing Term::ReadLine::Gnu while the Perl script is running and using the module in the script

我正在編寫供其他人使用的程序。 設計規范之一是使用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;

大多數用戶都不會安裝此程序,我想在程序運行時安裝它。

您在這里逆流而行。 沒有其他人會這樣做,在安裝后更改系統也會使我認識的大多數系統管理員不滿意。

只需聲明依賴項,以便在安裝程序時也安裝T :: R :: G。 我鏈接到如何為舊系統創建內部版本中的相關文檔

該工具鏈已經為您提供了所有必要的工具,以使參與其中的每個人都輕松無憂,並了解它。

您可以從“ cpan”命令本身學習。 cpan可以自己安裝(升級)並隨后重新加載所有使用的模塊。 那應該是學習的良好起點。

我在Term::ReadLine的代碼中看到,它確定了加載時將使用哪種實現,而不是調用new時。 因此,我建議按以下順序進行:

  1. 像您當前一樣測試Term::ReadLine::Gnu可用性,但是在加載任何ReadLine模塊之前
  2. 如果不存在,請安裝Term::ReadLine::Gnu
  3. require Term::ReadLine
  4. Term::ReadLine->new創建對象

事情變得更加復雜,因為Term::ReadLine::Gnu嘗試userequire直接加載它時拋出錯誤,因此即使安裝了簡單的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";

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM