R에서 패키지 작성을 위해 message ()가 print ()보다 나은 선택 인 이유는 무엇입니까?


82

진단 메시지를 인쇄 할 message()때보 다 왜 더 나은 선택 인지 알고 싶습니다 print().

예를 들어, print()함수 'iris'는와 같은 R 객체를 인쇄하는 데 더 나은 선택 이지만, message()문자열을 연결하려는 경우 message("a", "b")에는 더 좋습니다 print(paste0("a", "b")).

그러나 위에 나열된 단순한 것보다 더 많은 차이점이 있다고 생각합니다. 두 가지 방법에 대한 설명서를 읽었습니다.

그러나 내 질문에 기대했던 것만 큼 유익하지 않은 것 같습니다.

누군가가 어떤 경우 message()보다 낫고 print()그 이유를 알려 주시면 감사하겠습니다 .


1
@MartinMorgan, 나는 이것에 대부분 동의하지만 message()또한 suppressMessages()캡처 하는 "메시지"를 신호 합니다. suppressMessages()순수한 stderr 출력을 억제하지 마십시오. 예를 들어 콘솔에 suppressMessages(cat("hello\n", file=stderr()))여전히 표시됩니다 hello.
HenrikB

@HenrikB stop, warning, message만드는 것입니다 모든 신호 조건, 그들 캐치 / 억제-수 tryCatch(message("hello"), message=force); cat(file=stderr())의도가 진단 조건을 알리는 것이라면 스타일이 좋지 않습니다 (예에서 알 수 있듯이 비효율적입니다!).
Martin Morgan

답변:


146

TL; DR

S3 객체에 cat()대한 print.*()함수를 만들 때 사용해야 합니다. 그 밖의 모든 message()경우에는 프로그램 상태에 문제가없는 한 사용해야합니다 . 예를 들어 복구 가능한 잘못된 오류는 오류를 warning()중지 하는 것과 비교합니다 stop().

이 게시물의 목적은 패키지 개발자가 액세스 할 수있는 다양한 출력 옵션에 대한 피드백을 제공하고 잠재적으로 새 객체 또는 문자열을 기반으로하는 출력을 구성하는 방법을 제공하는 것입니다.

R 출력 개요

기존의 출력 기능은 다음과 같습니다.

  1. print()
  2. cat()
  3. message()
  4. warning()
  5. stop()

이제 처음 두 함수 ( print()cat())는 출력을 stdout또는 표준 출력으로 보냅니다 . 마지막 세 함수 ( message(), warning()stop())는 출력을 stderr또는 표준 오류 로 보냅니다 . 즉, 다음 과 같은 명령 의 결과 출력lm()하나의 파일로 전송되고 오류 출력 (있는 경우)은 완전히 별도의 파일로 전송됩니다. 이는 진단이 로그 파일의 결과 출력을 복잡하게 하지 않고 오류를 신속하게 검색 할 수 있으므로 사용자 경험에 특히 중요합니다 .

사용자 및 외부 패키지를위한 디자인

이제 위의 내용은 I / O 사고 방식에 더 많이 포함되어 있으며 반드시 사용자를 향한 프레임 셋은 아닙니다. 따라서 일상적인 R 사용자의 맥락에서 이에 대한 동기 부여를 제공하겠습니다. 특히, 3-5 또는 사용하여 stderr기능들이 출력 통해 콘솔 텍스트 땜질 않고 억제 할 수있다 sink()capture.output(). 억제는 일반적으로 suppressWarnings(),, suppressMessages()등 의 형태로 제공 suppressPackageStartupMessages()됩니다. 따라서 사용자는 결과에 직면 한 결과에만 직면하게됩니다. 이는 knitr , rmarkdown 또는 Sweave 를 통해 동적 문서를 만들 때 사용자가 텍스트 기반 출력을 해제 할 수있는 유연성을 허용하려는 경우 특히 중요합니다 .

특히, knitr같은 청크 옵션을 제공합니다 error = F, message = F하고 warning = F. 이를 통해 문서에서 명령에 수반되는 텍스트를 줄일 수 있습니다. 또한 results = "hide"모든 출력을 비활성화 하는 옵션을 사용할 필요가 없습니다 .

출력의 특성

인쇄()

먼저, 우리는 오래된 사람이지만 좋은 사람이 있습니다 print(). 이 기능에는 몇 가지 심각한 제한이 있습니다. 그중 하나는 용어의 내장 된 연결이 없다는 것입니다. 두 번째, 아마도 더 심각한 것은 각 출력 앞에 [x]실제 내용에 대한 인용문 이 뒤따른 다는 사실입니다 . x이 경우는 요소 번호가 인쇄되기 말한다. 이것은 디버깅 목적에 도움이되지만 그 외에는 어떤 용도로도 사용되지 않습니다.

예 :

print("Hello!")

[1] "Hello!"

연결의 경우 다음 paste()과 동기화하여 작동 하는 함수에 의존합니다 print().

print(paste("Hello","World!"))

[1] "Hello World!"

또는 의 매개 변수 에 의해 관리되는 요소 사이 의 기본 사용을 피하기 위해 paste0(...)대신 함수를 사용할 수 있습니다 . (공백없는 연결)paste(...)spacepaste()sep = " "

예 :

print(paste0("Hello","World!"))

[1] "HelloWorld!"

print(paste("Hello","World!", sep = ""))

[1] "HelloWorld!"

고양이()

반대로, cat()이러한 모든 비판을 다룹니다. 대부분의 특히, sep=" "의 매개 변수 paste()기능은 쓰기를 건너 뛸 하나를 수에 내장되어 paste()cat(). 그러나 cat()함수의 유일한 단점은 \n끝 부분에 추가 또는 fill = TRUE(기본 인쇄 너비 사용) 를 통해 새 줄을 강제로 적용해야한다는 것 입니다.

예 :

cat("Hello!\n")
Hello!

cat("Hello","World!\n")
Hello World!

cat("Hello","World!\n", sep = "")
HelloWorld!

이것이 바로 S3 방법을 cat()설계 할 때 사용해야하는 이유 print.*()입니다.

메시지()

message()기능도보다 한 단계 더 cat()! 출력되는 이유는 stderr대신에 지정 되는 기존 일반 텍스트와 다릅니다 stdout. 예 : 사용자의 시선을 사로 잡기 위해 표준 검정 출력에서 ​​빨간색 출력으로 색상을 변경했습니다.

메시지 출력

또한 내장 paste0()기능이 있습니다.

message("Hello ","World!") # Note the space after Hello
"Hello World!"

또한 다음 message()과 함께 사용할 수있는 오류 상태를 제공합니다.tryCatch()

예 :

 tryCatch(message("hello\n"), message=function(e){cat("goodbye\n")})
 goodbye

경고()

warning()기능은 부담없이 사용할 수있는 것이 아닙니다. 경고 기능은 주로 접두어 ( "Warning message:")에 행이 추가되어 메시지 기능과 구별 되며 그 상태는 문제가있는 것으로 간주됩니다.

경고 출력

기타 : 함수에서 우연히 사용하면 일반적으로 "오류"로 처리되는 예제 검사 및 경고로 인해 패키지를 CRAN 에 업로드하는 동안 실수로 비탄을 유발할 수 있습니다 .

중지()

마지막으로 stop(). 이것은 당면한 작업을 완전히 종료하고 사용자에게 제어권을 되돌림으로써 경고를 다음 단계로 가져옵니다. 또한 "Error:"추가 되는 용어와 함께 가장 심각한 접두사가 있습니다.

오류 출력


어떤 차이점은 무엇 message("hello world")cat("hello world", sep="\n")인쇄를 디자인 할 때. * S3 방법은?
antonio

1
@antonio : message()빨간색 텍스트가 표시되고 다른 텍스트는 표시되지 않습니다. 당신이 변수를 추가하면 이제 cat, 예를 들어 cat("hello world", "antonio", sep="\n"), 차이는 하나 개에 부합 될 것 hello world와 다른 antonio. 그러나 message()모든 것을 동일한 라인에 유지합니다.
코트리스

1
좋은 답변에 감사드립니다. 비슷한 것을 찾고 있었지만 내 질문은 "게으른"레이블이
burger

1
SJD

1
@WaldirLeoncio "진단"출력은 예를 들어 "레벨 정보"에서 인쇄되는 것입니다. 불행하게도, 그 개념과 존재하지 않는 message()cat(). 나는 (예 : 대부분의 시스템의 경우 오늘날과 같이 R에 대한 성숙한 로깅 인터페이스가 있는지를 보았다 SLF4J의 Java 용 API), 거기 입니다 : futile.logger는 - 에서 CRAN .
David Tonhofer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.