2015-09-28 16 views
6

Tôi có một hàm tổng quát để nắm bắt tất cả các trường hợp ngoại lệ bao gồm trong gói của tôi logR::tryCatch2 định nghĩa là:Gọi gián đoạn từ mã R

tryCatch2 <- function(expr){ 
    V=E=W=M=I=NULL 
    e.handler = function(e){ 
     E <<- e 
     NULL 
    } 
    w.handler = function(w){ 
     W <<- c(W, list(w)) 
     invokeRestart("muffleWarning") 
    } 
    m.handler = function(m){ 
     attributes(m$call) <- NULL 
     M <<- c(M, list(m)) 
    } 
    i.handler = function(i){ 
     I <<- i 
     NULL 
    } 
    V = suppressMessages(withCallingHandlers(
     tryCatch(expr, error = e.handler, interrupt = i.handler), 
     warning = w.handler, 
     message = m.handler 
    )) 
    list(value=V, error=E, warning=W, message=M, interrupt=I) 
} 

Như bạn có thể thấy trong dòng cuối cùng nó trả về một danh sách đó là ít nhiều tự mô tả.
Nó làm cho các phản ứng thực sự đối với trường hợp ngoại lệ trì hoãn sau khi tryCatch2 cuộc gọi bằng cách đơn giản !is.null:

f = function(){ warning("warn1"); warning("warn2"); stop("err") } 
r = tryCatch2(f()) 
if(!is.null(r$error)) cat("Error detected\n") 
# Error detected 
if(!is.null(r$warning)) cat("Warning detected, count", length(r$warning), "\n") 
# Warning detected, count 2 

Nó hoạt động như mong đợi, tôi có thể phản ứng với mã của riêng tôi. Nhưng trong một số trường hợp, tôi không muốn dừng quá trình ngắt cũng bị chặn. Tại thời điểm này có vẻ như tôi sẽ cần phải thêm tham số bổ sung để tryCatch2 mà sẽ kiểm soát nếu ngắt nên được nắm bắt hay không. Vậy câu hỏi hỏi về một số invokeInterrupt chức năng mà tôi có thể sử dụng theo cách sau:

g = function(){ Sys.sleep(60); f() } 
r = tryCatch2(g()) 
# interrupt by pressing ctrl+c/stop while function is running! 
if(!is.null(r$interrupt)) cat("HERE I would like to invoke interrupt\n") 
# HERE I would like to invoke interrupt 

Tôi nghĩ rằng nếu R có khả năng bắt một nó nên cũng có thể gọi một.
Làm cách nào để có thể đạt được chức năng invokeInterrupt?

+0

Tại sao không thay đổi giao diện? Thay vì 'if (! Is.null (r $ interrupt))', cung cấp một hàm để người dùng phải làm 'if (r $ has_interrupt())', và bạn có thể gọi ngắt trong hàm đó. –

+0

@KonradRudolph để làm điều này tôi vẫn cần phải biết làm thế nào để gọi ngắt từ mã R, phải không? – jangorecki

+1

Ah, tôi hiểu nhầm câu hỏi rồi. Tôi thực sự không nhận thức được một cách nào đó trong R để làm điều đó, và nếu tôi hiểu một số tài liệu chính xác thì nó hoàn toàn không thể. –

Trả lời

3

Tôi có thể đề xuất giải pháp một phần, dựa trên gói tools.

invokeInterrupt <- function() { 
    require(tools) 
    processId <- Sys.getpid() 
    pskill(processId, SIGINT) 
} 

Tuy nhiên, lưu ý rằng ném tín hiệu ngắt (SIGINT) với pskill không xuất hiện là rất mạnh mẽ. Tôi đã chạy một vài thử nghiệm bằng cách gửi ngoại lệ và bắt nó bằng chức năng của bạn, như vậy:

will_interrupt <- function() { 
    Sys.sleep(3) 
    invokeInterrupt() 
    Sys.sleep(3) 
} 

r = tryCatch2(will_interrupt()) 

Trên Linux, điều này hoạt động tốt khi được thực thi từ dòng lệnh R. Trên cửa sổ, dòng lệnh R và R Gui đã đóng khi thực thi mã này. Có tồi tệ hơn: trên cả linux và windows, mã này bị lỗi Rstudio ngay lập tức ...

Vì vậy, nếu mã của bạn được thực hiện từ dòng lệnh R trên Linux, giải pháp này sẽ ổn. Nếu không, bạn có thể không may mắn ...

+0

Mẹo hay. Nó sẽ không hoạt động trong trường hợp của tôi, tôi muốn gọi * ngắt * từ chức năng mức thấp nhưng sau đó có thể bắt được một vài khung hình cao hơn trong ngăn xếp cuộc gọi bằng cách sử dụng một cuộc gọi 'tryCatch2' khác. – jangorecki

+0

Tôi không phát hiện ra 'SIGINT' trước đây (Tôi không biết tín hiệu tồn tại). Tôi đã thử nghiệm nó và có vẻ như không bắt ngắt trên một cách chính xác. Một nửa số tiền thưởng có vẻ công bằng. Tôi tự hỏi tại sao trong-R ngắt là khác nhau từ tín hiệu 'SIGINT', và nếu nó không nên giống nhau? – jangorecki

+0

Tôi rất thích xem giải pháp tốt hơn so với phiên bản tôi đăng (thực sự là cụ thể vì nó chỉ hoạt động với linux), do đó, không chấp nhận giải pháp này và hãy đợi xem có ai đó có thể giải quyết vấn đề này không :) – Jealie

Các vấn đề liên quan