Установка Term :: ReadLine :: Gnu во время работы скрипта Perl и использование модуля в скрипте - PullRequest
0 голосов
/ 07 мая 2011

Я пишу программу, которую могут использовать другие. Одна из спецификаций проекта - использовать библиотеку Perm Term :: ReadLine :: Gnu. У большинства пользователей этого не будет, и я хочу установить его во время работы программы.

Итак, когда пользователь запускает программу, у него нет установленной библиотеки. Моя программа установит их для них, пока они используют программу с помощью менеджера пакетов ОС.

Вот как я проверяю модуль

         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);
          }

К сожалению, я получаю эту ошибку при попытке использовать файл истории:

Невозможно найти метод объекта "using_history" через пакет "Term :: ReadLine :: Stub" в ./msi.pl, строка 618, строка 2.

строка 618 -

          $TERMINAL->using_history();

Что является первым использованием объекта $ TERMINAL.

Кто-нибудь имел опыт установки модулей Perl во время работы сценария и последующего использования модулей в этом же сценарии?

Хорошо ... Спасибо Энди, если модуль не установлен, это работает

          # 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
            }

Теперь, однако, проверка на установленный мод всегда терпит неудачу, я думаю, потому что

            require Term::ReadLine::Gnu;

нужно

            require Term::ReadLine;

рано в коде, как старый

     require Term::ReadLine;

     my $Readline_Support = 1;
     eval { require Term::ReadLine::Gnu }
       or $Readline_Support = 0;

Ответы [ 3 ]

2 голосов
/ 08 мая 2011

У большинства пользователей не будет установлено это, и я хочу установить его во время работы программы.

Вы плывете против течения здесь.Никто другой не делает это таким образом, и смена системы после установки также расстроит большинство системных администраторов, которых я знаю.

Просто объявите зависимость, поэтому, когда ваша программа установлена, T :: R :: G такжеустановлены.Я ссылаюсь на соответствующую документацию в Как создать сборку для унаследованной системы? .

Набор инструментов дает вам уже все необходимые биты, чтобы сделать это безболезненным для всех, кто вовлеченузнать об этом.

1 голос
/ 07 мая 2011

Вы можете учиться у самой команды "cpan". cpan может сам установить (обновить) и перезагрузить все использованные модули. Это должно стать хорошей отправной точкой для обучения.

0 голосов
/ 07 мая 2011

Я вижу в коде для Term::ReadLine, что он определяет, какую реализацию он будет использовать во время загрузки, а не когда вызывается new.Поэтому я бы предложил следующую последовательность:

  1. проверка доступности Term::ReadLine::Gnu точно так же, как вы сейчас, но перед загрузкой любых ReadLine модулей
  2. установите Term::ReadLine::Gnu, если нетприсутствует
  3. require Term::ReadLine
  4. создать свой объект с помощью 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";
...