withCallingHandlers() i restarty
Używaj withCallingHandlers() do obsługi warunków w sposób nielokalny.
withCallingHandlers() i restarty to bezpłatna lekcja R Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.
tryCatch a withCallingHandlers
Najważniejsza różnica polega na tym, że tryCatch() ustanawia nielokalne wyjście — po przechwyceniu warunku sterowanie opuszcza wyrażenie i już do niego nie wraca. withCallingHandlers() zachowuje stos wywołań i może wznowić wykonywanie po obsłużeniu warunku.
# tryCatch: execution does NOT continue after warning
tryCatch({
warning('first')
cat('This line is never reached\n')
}, warning = function(w) cat('tryCatch caught:', w$message, '\n'))withCallingHandlers zachowuje wykonywanie
W przypadku withCallingHandlers() procedura obsługi jest wykonywana, ale działanie jest kontynuowane po zgłoszeniu warunku (chyba że sama procedura obsługi zgłosi błąd lub wywoła restart). Stos wywołań nie jest rozwijany.
withCallingHandlers({
warning('first warning')
cat('Execution continues here\n')
warning('second warning')
cat('And here too\n')
}, warning = function(w) {
cat('Handler saw:', w$message, '\n')
invokeRestart('muffleWarning')
})Restart muffleWarning
Wywołanie invokeRestart('muffleWarning') wewnątrz procedury obsługi ostrzeżenia zapobiega wyświetleniu ostrzeżenia przez domyślną procedurę obsługi R. Bez tego po wykonaniu Państwa procedury obsługi R nadal wyświetliłby ostrzeżenie za pomocą domyślnego mechanizmu.
# Without muffleWarning: warning still shows after handler
withCallingHandlers({
warning('test')
}, warning = function(w) {
cat('Handler ran\n')
# no muffleWarning: default handler still fires
})Restart muffleMessage
Podobnie invokeRestart('muffleMessage') wewnątrz procedury obsługi komunikatu wycisza komunikat po przetworzeniu go przez niestandardową procedurę obsługi. Na tym mechanizmie opiera się suppressMessages().
withCallingHandlers({
message('Progress: 50%')
message('Progress: 100%')
}, message = function(m) {
cat('[LOG]', trimws(m$message), '\n')
invokeRestart('muffleMessage')
})Rejestrowanie ostrzeżeń bez zatrzymywania działania
Praktyczne zastosowanie withCallingHandlers() polega na zbieraniu ostrzeżeń do wektora dziennika i jednoczesnym pozwoleniu kodowi na dokończenie działania. tryCatch() zatrzymałoby się przy pierwszym ostrzeżeniu, natomiast withCallingHandlers() zbiera je wszystkie.
warnings_log <- character(0)
result <- withCallingHandlers({
x <- log(-1)
y <- sqrt(-4)
c(x, y)
}, warning = function(w) {
warnings_log <<- c(warnings_log, w$message)
invokeRestart('muffleWarning')
})
cat('Warnings logged:', length(warnings_log), '\n')
cat(warnings_log, sep = '\n')Koncepcja invokeRestart()
Restarty to wstępnie zdefiniowane strategie odzyskiwania, które może udostępnić kod zgłaszający warunek. invokeRestart(name) wybiera jedną z tych strategii. Wbudowane restarty obejmują 'muffleWarning' i 'muffleMessage'; własne można definiować za pomocą withRestarts().
# withRestarts() offers named recovery options
divide_safe <- function(x, y) {
withRestarts(
{
if (y == 0) stop('division by zero')
x / y
},
use_zero = function() 0,
use_na = function() NA
)
}
# A handler can pick a restart
withCallingHandlers(
divide_safe(10, 0),
error = function(e) invokeRestart('use_zero')
)Łączenie withCallingHandlers i tryCatch
Można je zagnieżdżać: należy użyć zewnętrznego withCallingHandlers() do rejestrowania lub zliczania warunków, a wewnętrznego tryCatch() do zapewnienia wartości zastępczej. Zewnętrzna procedura obsługi widzi warunek jako pierwsza.
n_warnings <- 0L
result <- withCallingHandlers(
tryCatch(log(-1), warning = function(w) -999),
warning = function(w) {
n_warnings <<- n_warnings + 1L
cat('Logged warning #', n_warnings, '\n')
}
)
cat('Result:', result, '\n')Niestandardowe klasy warunków
Niestandardowe klasy warunków można tworzyć, wywołując structure() dla listy z klasą c('myError', 'error', 'condition'). Procedury obsługi dopasowują się według klasy, dlatego niestandardowe klasy pozwalają przechwytywać konkretne typy błędów bez przechwytywania wszystkich błędów.
my_error <- function(msg, data = NULL) {
structure(
class = c('my_error', 'error', 'condition'),
list(message = msg, data = data)
)
}
tryCatch(
stop(my_error('custom error', data = 42)),
my_error = function(e) cat('Custom handler, data=', e$data, '\n'),
error = function(e) cat('Generic handler\n')
)Kiedy używać withCallingHandlers
Należy używać withCallingHandlers(), gdy chce się obserwować lub rejestrować warunki bez zatrzymywania działania. tryCatch() należy stosować, gdy chce się obsłużyć warunek i zwrócić alternatywną wartość. Narzędzia te rozwiązują różne problemy.
# withCallingHandlers: observe all, continue
withCallingHandlers(
for (x in c(4, -1, 9, -4)) cat(suppressWarnings(sqrt(x)), ''),
warning = function(w) cat('[warn]', '')
)
cat('\n')Łańcuch zgłaszania warunku
Po zgłoszeniu warunku R przechodzi w górę stosu wywołań w poszukiwaniu procedur obsługi. Procedury obsługi withCallingHandlers() działają w kontekście dynamicznym (ze zachowanym stosem wywołań). Procedury obsługi tryCatch() działają po rozwinięciu stosu — pierwotny kontekst jest już niedostępny.
# Demonstrate: withCallingHandlers handler can see full stack
f <- function() {
withCallingHandlers(
g(),
warning = function(w) {
cat('Caught in f, stack length:', sys.nframe(), '\n')
invokeRestart('muffleWarning')
}
)
}
g <- function() warning('from g')
f()Implementacja suppressWarnings()
suppressWarnings(expr) jest zasadniczo równoważne withCallingHandlers(expr, warning = function(w) invokeRestart('muffleWarning')). Zrozumienie tego mechanizmu pozwala tworzyć własne warianty wyciszające tylko określone typy ostrzeżeń.
# Suppress only NaN warnings, not others
suppress_nan_warn <- function(expr) {
withCallingHandlers(expr, warning = function(w) {
if (grepl('NaN', conditionMessage(w)))
invokeRestart('muffleWarning')
})
}
suppress_nan_warn(log(-1)) # NaN warning suppressed
tryCatch(
suppress_nan_warn(warning('other issue')),
warning = function(w) cat('Other warning kept:', w$message, '\n')
)Szybkie sprawdzenie
Na czym polega główna różnica między withCallingHandlers() a tryCatch()?
Restarty: najważniejsze informacje
Najważniejsze informacje dotyczące withCallingHandlers i restartów:
withCallingHandlers()= lokalna procedura obsługi, zachowany stos wywołań, możliwość kontynuowania działaniatryCatch()= nielokalne wyjście, rozwinięty stos, możliwość zwrócenia alternatywnej wartościinvokeRestart('muffleWarning')wycisza domyślne wyświetlanie ostrzeżeniainvokeRestart('muffleMessage')wycisza domyślne wyświetlanie komunikatuwithCallingHandlers()służy do zbierania lub rejestrowania wszystkich warunków bez zatrzymywania działania- Niestandardowe klasy warunków umożliwiają wybiórcze przechwytywanie konkretnych typów błędów
log_vec <- character(0)
withCallingHandlers({
message('start')
warning('low memory')
message('end')
}, message = function(m) {
log_vec <<- c(log_vec, paste('MSG:', trimws(m$message)))
invokeRestart('muffleMessage')
}, warning = function(w) {
log_vec <<- c(log_vec, paste('WARN:', w$message))
invokeRestart('muffleWarning')
})
cat(log_vec, sep = '\n')Często zadawane pytania
Czy lekcja „withCallingHandlers() i restarty” jest bezpłatna?
Tak — pełny tekst „withCallingHandlers() i restarty” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „withCallingHandlers() i restarty”?
Używaj withCallingHandlers() do obsługi warunków w sposób nielokalny. Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć R Academy?
Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „withCallingHandlers() i restarty”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?
Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Błędy, ostrzeżenia i komunikaty w R
- tryCatch() do obsługi błędów
- withCallingHandlers() i restarty
- Pisanie odpornych funkcji za pomocą stop() i warning()