Perl: вызов функции в конструкторе? - PullRequest
2 голосов
/ 14 апреля 2011


Я хотел бы улучшить мой Perl-скрипт, который выполняет SNMP-запрос на коммутатор Cisco. Но я не очень понимаю конструктор и предоставление аргументов для работы в Perl ...
Это мой сценарий:

#!/usr/bin/perl
use strict;
use warnings;
use Net::SNMP;
package SnmpTable;

my ($session, $error);

sub new {
  my ($classe, $hostname, $oid, $community) = @_;
  my $this = {
    "hostname"      => $hostname,
    "oid"           => $oid,
    "community" => $community
  };
  bless($this, $classe);
  return $this;
}

sub connexion {
    my ($this) = @_;
    #print "Connexion SNMP...\n";
    ($session, $error) = Net::SNMP->session(
        -hostname  => $this->{hostname},
        -community => $this->{community},
        -version   => "1",
        -timeout   => 3,
    );
    request_error_connexion() if (!defined($session));
    #print "Connexion établie\n";
}

sub request_error_connexion {   
    my ($this) = @_;
    print "Erreur : connexion SNMP impossible vers $this->{hostname}\n";
    print "Erreur : $error\n";
    if ($error =~ /The argument "-community" is unknown/)
        {
                # protocol SNMP version 3 non pris en charge
                exit 3;  # code retour final = 3*256 = 768
        }
    else
    {
        exit 1; # code retour final = 1*256 = 256
    }
}

sub request_error {
        my ($this) = @_;
        #print "Erreur : pas de réponse SNMP depuis l'hôte $this->{hostname} avec l'oid $this->{oid}\n";
        printf "Erreur : %s\n",$session->error;
        if ($session->error =~ /No response from remote host/)
        {
                #host ok, mais community surement erronée ou host refuse le connexion
                $session->close;
                exit 2; # code retour final = 2*256 = 512
        }
        else
        {
                #table introuvable
                $session->close;
                exit 4; # code retour final = 4*256 = 1024
        }
}

sub requete {
    my ($this) = @_;
    my $result = $session->get_table( -baseoid => $this->{oid} );
    request_error() if (!defined($result));
    my %tab = ();

    foreach my $i (Net::SNMP::oid_lex_sort(keys %{$result})) {
        my $index = $i;
        $index =~ s/$this->{oid}.//;
        $tab{ $index } = $result->{$i};  
        #print $index."--".$result->{$i}."\n";
    }

    $session->close();
    return %tab;
}

1;

В моем конструкторе я хотел бы создать сеанс SNMP (используя Net :: SNMP), а не делать это в функции 'connexion ()'. Когда я создаю экземпляр, connectxion () вызывается автоматически.
Кроме того, я хочу, чтобы функция 'Requete ()' с аргументом arg (OID).
Таким образом, я мог создать только один экземпляр и выполнить все мои запросы с ним.
С помощью этого сценария я должен создавать экземпляры столько информации, сколько мне нужно.

Надеюсь, это понятно ... Спасибо.

Ответы [ 2 ]

2 голосов
/ 14 апреля 2011

Я не на 100% уверен, что ваш вопрос, но вот попытка ответить:

  1. Как аргументы подпрограммы работают в Perl?
  2. КакРабота конструктора в Perl?

Ответы:

Как работают аргументы подпрограмм?

Подпрограммы в Perl немного необычны.См. Perldoc perlsub для всех деталей.

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

Список аргументов хранится в специальном массиве @_.Члены @_ на самом деле являются псевдонимами передаваемых значений (представьте их в терминах передачи по ссылке), поэтому можно изменить вызывающий аргумент.Чтобы избежать несчастных случаев, большинство подпрограмм копирует элементы @_ в локальные переменные.Когда вы видите my ($foo, $bar) = @_;, он копирует первых двух членов @_ в $foo и $bar.Еще одна распространенная идиома - my $foo = shift;.Это удаляет первый элемент из @_ и копирует его в $foo.

Как работает конструктор?

В Perl методы OO - это просто подпрограммы, и конструктор ничем не отличается.

Когда вы вызываете метод $foo->do_this() или MyCoolClass->new() элемент в левой части оператора -> называется invocant .Инвокант определяет, в каких пространствах имен (пакеты в терминах perl) будет выполняться поиск метода.Когда инвокант является строковым литералом, он считается именем пакета или класса, в котором начинается поиск. Когда инвокант является скалярным, он должен быть объектом.В любом случае инвокант также передается в качестве первого аргумента методу, когда он найден и вызван.Таким образом, метод класса (такой как new()) будет ожидать строку для своего первого аргумента, в то время как метод экземпляра будет ожидать объект.

Конструктор, обычно new(), обычно это метод класса, который создаетэкземпляр класса, к которому он принадлежит.Поэтому Foo->new() создаст новый объект Foo.

Объект perl - это любая ссылка, которая была связана с пакетом с помощью функции bless.

Давайте посмотрим на вашконструктор и посмотрите, как он работает:

sub new {

  # Unpack @_ into local variables
  # Notice that the class name is the first argument.
  my ($classe, $hostname, $oid, $community) = @_;


  # Create a reference to a hash with the arguments associated 
  # to particular keys in the hash.
  my $this = {
    "hostname"      => $hostname,
    "oid"           => $oid,
    "community" => $community
  };

  # Associate the hash ref with the class
  bless($this, $classe);

  # $this is now an object.  You can make method calls on it here.


  return $this;
}

Поскольку конструктор подобен любому другому методу или подпрограмме в Perl, вы можете делать в нем все, что захотите.Обычно считается хорошей идеей сохранять ваши подпрограммы как можно более простыми, но нет никаких причин, по которым вы не можете создать объект Net :: SNMP в своем конструкторе.Если вы его сделаете, вам, вероятно, следует сохранить его для дальнейшего использования.

sub new {
  my ($classe, $hostname, $oid, $community) = @_;

  my $this = {
    "hostname"      => $hostname,
    "oid"           => $oid,
    "community"     => $community,
    "connexion"     => undef,
  };

  bless($this, $classe);

  # Store the connection for later.
  # You could also modify connexion so that it stores the connection for you.
  $this->{connexion} = $this->connexion;

  return $this;
}

Весь этот код предполагает, что мы хотим использовать классические методы Perl OOP.Хотя эти методы работают хорошо, вокруг среды Moose Perl OO существует огромное количество активности.Moose упрощает написание твердого, хорошо инкапсулированного ОО-кода на Perl.

Я настоятельно рекомендую вам взять копию книги, например Modern Perl .Он даст вам обновленный взгляд на OO-инструменты Perl, введение в Moose, а также продемонстрирует множество простых техник, которые значительно упростят поддержку вашего кода.

Надеюсь, это полезно.

2 голосов
/ 14 апреля 2011

В new, перед return введите это:

$this->connexion;

В часть параметра OID:

sub requete {
    my ($this, $oid) = @_;

    $oid = $this->{oid}
        unless defined $oid;

    my $result = $session->get_table( -baseoid => $oid );
    request_error() if (!defined($result));
    my %tab = ();

    foreach my $i (Net::SNMP::oid_lex_sort(keys %{$result})) {
        my $index = $i;
        $index =~ s/$this->{oid}.//;
        $tab{ $index } = $result->{$i};  
        #print $index."--".$result->{$i}."\n";
    }

    $session->close();
    return %tab;
}

Это будет принимать OID в качестве параметра, это OIDне указан в качестве параметра, он будет использовать OID из конструктора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...