Perl에서 경고 메시지, 예외 정보 캡처 및 로그 세부 정보 쓰기

모든 Perl 스크립트와 모듈에서 경고를 켜는 것을 권장하지만, 사용자는 Perl이 보내는 경고를 보고 싶지 않습니다.
한편으로는 코드 앞에서use warnings를 보안망으로 사용하고 싶고, 다른 한편으로는 화면에 경고가 나타납니다.대부분의 경우 고객은 이 경고를 어떻게 처리해야 할지 모른다.만약 운이 좋다면 이 경고들은 단지 고객을 놀라게 할 뿐이다. 물론 불행하게도 그들은 그것들을 복구하려고 시도하고 있다.(여기서 말하는 것은 Perl 프로그래머가 아니다.)
세 번째는 경고를 저장해서 분석하고 싶을지도 모른다.
그 밖에 많은 곳에서 Perl 스크립트와 응용 프로그램이 use warnings를 사용하지 않고 #!행에서 -w를 사용합니다.use warnings를 추가하면 대량의 경고가 발생할 수 있습니다.
장기적으로는 당연히 이런 경고를 없애야 하지만 단기적으로는?
장기적인 계획이라도 버그가 전혀 없는 코드를 쓸 수 없고, 응용 프로그램이 앞으로 경고 메시지를 영원히 출력하지 않을 것을 보장할 수 없다.
할 수 있겠소?
너는 경고가 화면에 인쇄되기 전에 그것들을 잡을 수 있다.
신호
Perl에는%SIG라는 내장hash표가 있는데 그 중의 키는 운영체제 신호의 이름이다.대응하는 값은 함수 (대다수는 함수 인용) 이며, 이 함수들은 특정한 신호가 촉발될 때 호출된다.
Perl은 시스템에서 제공하는 표준 신호 외에 두 개의 내부 신호를 추가했습니다.그중 하나는 , 코드가warn () 함수를 호출할 때마다 터치합니다.또 하나는 __DIE__,이것은 die () 를 호출할 때마다 터치합니다.
본고에서 우리는 이것이 어떻게 경고 메시지에 영향을 미치는지 볼 수 있다.
익명 함수
sub {}는 익명 함수, 즉 함수체만 있고 이름이 없는 함수입니다.(이 예에서도 함수체는 비어 있지만, 나는 네가 나의 뜻을 이해하길 바란다.)
캡처 경고 - 처리 안 함
다음 코드를 추가하는 경우:

  local $SIG{__WARN__} = sub {
     #
  };
이것은 실제로 프로그램의 어딘가에 경고 메시지가 생겼을 때 아무런 처리도 하지 않는다는 것을 나타낸다.기본적으로 이것은 모든 경고를 숨길 것이다.
경고 캡처 - 예외로 변환
You could also write: 너도 다음과 같이 쓸 수 있다.

  local $SIG{__WARN__} = sub {
    die;
  };
이렇게 하면 경고가 발생할 때마다die () 를 호출합니다. 즉, 모든 경고를 이상으로 변환합니다.
이상에 경고 메시지를 포함하려면 다음과 같이 하십시오.

  local $SIG{__WARN__} = sub {
    my $message = shift;
    die $message;
  };
실제 경고 정보는 익명 함수에 유일한 매개 변수로 전달됩니다.
경고 캡처 - 로그 작성
너는 아마도 중간에서 다른 일을 하고 싶을 것이다.
시끄러운 경고 메시지를 필터링하고 나중에 분석합니다.

  local $SIG{__WARN__} = sub {
    my $message = shift;
    logger($message);
  };
여기에서 우리는 logger () 가 네가 실현한 로그 함수라고 가정한다.
일지를 쓰다
응용 프로그램에 로그 메커니즘이 있다고 가정해 보세요.없으면 덧붙이는 게 좋겠어요.설령 네가 추가할 수 없다 하더라도, 너는 운영체제의 내장 로그 메커니즘이 필요하다.예를 들어 Linux의syslog, MS Windows의 Event Logger, 다른 운영체제도 그들 내부의 로그 메커니즘을 가지고 있다.
본고의 예에서 우리는 자제logger () 함수를 사용하여 이 생각을 대표한다.
로그를 캡처하고 쓰는 전체 예

  #!/usr/bin/perl
  use strict;
  use warnings;
 
  local $SIG{__WARN__} = sub {
    my $message = shift;
    logger('warning', $message);
  };
 
  my $counter;
  count();
  print "$counter
";
  sub count {
    $counter = $counter + 42;
  }
 
 
  sub logger {
    my ($level, $msg) = @_;
    if (open my $out, '>>', 'log.txt') {
        chomp $msg;
        print $out "$level - $msg
";
    }
  }
위의 코드는 로그에 있습니다.txt 파일에 다음 행을 추가합니다.

  Use of uninitialized value in addition (+) at code_with_warnings.pl line 14.
변수 $counter와 함수 count () 는 경고 예시의 일부분일 뿐입니다.
경고 처리 함수의 경고 정보
__WARN__처리 함수가 실행되는 동안 자동으로 비활성화됩니다.따라서 경고 처리 함수 실행 과정에서 발생하는 (신규) 경고 정보는 무한 순환을 일으키지 않습니다.
퍼블릭 문서에서 더 많은 세부 사항을 알 수 있습니다.
Avoid multiple warnings
주의해야 할 것은 중복된 경고 메시지가 로그 파일을 가득 채울 수 있다는 것이다.나는 반복 경고 정보의 수를 줄이기 위해 간단한 캐시 기능을 사용할 수 있다.

#!/usr/bin/perl
  use strict;
  use warnings;
 
 
  my %WARNS;
  local $SIG{__WARN__} = sub {
      my $message = shift;
      return if $WARNS{$message}++;
      logger('warning', $message);
  };
 
  my $counter;
  count();
  print "$counter
";
  $counter = undef;
  count();
 
  sub count {
    $counter = $counter + 42;
  }
 
  sub logger {
    my ($level, $msg) = @_;
    if (open my $out, '>>', 'log.txt') {
        chomp $msg;
        print $out "$level - $msg
";
    }
  }
$counter 변수를 undef로 지정한 다음count () 함수를 다시 호출해서 같은 경고를 하는 것을 볼 수 있습니다.
우리도 __WARN__의 처리 함수를 약간 복잡한 버전으로 바꿉니다.

  my %WARNS;
  local $SIG{__WARN__} = sub {
      my $message = shift;
      return if $WARNS{$message}++;
      logger('warning', $message);
  };
logger를 호출하기 전에 현재 문자열이%WARNShash 테이블에 있는지 확인합니다.없으면 logger () 를 추가하고 호출합니다.만약 이미 있다면, 리턴을 호출하고, 같은 이벤트를 두 번 기록하지 않습니다.
너는 우리가 uniquevalues in an array에서도 같은 아이디어를 사용했다는 것을 기억할 수 있다.
로컬이 뭐예요?
위의 모든 예에서 나는local 함수로 온돌 (경고 처리) 효과를 침식한다.엄밀히 말하면, 이러한 예에서 우리는 이렇게 할 필요가 없다. 왜냐하면 이 코드들이 메인 스크립트의 첫 번째 부분이라고 가정하기 때문이다.이런 상황에서는 상관없다. 어쨌든 전체 작용역 안에 있기 때문이다.
그러나 이렇게 쓰는 것이 가장 좋다.
local는 모듈에서 변경을 제한하는 데 매우 중요하다.특히 발표할 모듈은국부화되지 않으면 전체 응용 프로그램에 영향을 줄 수 있다.limit는 영향을 닫힌 코드 블록에 제한합니다.
전역적인%WARNS 사용 방지
Perl 5.10이나 업데이트된 버전을 사용하고 있다면, 전역 변수%WARNS를 바꾸기 위해 코드를 바꿀 수 있습니다.이렇게 하려면 스크립트의 시작에use v5.10을 사용해야 합니다.그리고 익명 함수 내부에서state 키워드를 사용하여 변수를 설명합니다.

  #!/usr/bin/perl
  use strict;
  use warnings;
 
  use v5.10;
 
  local $SIG{__WARN__} = sub {
      state %WARNS;
      my $message = shift;
      return if $WARNS{$message}++;
      logger('warning', $message);
  };

좋은 웹페이지 즐겨찾기