R komut dosyası satır numaraları hatalı mı?


105

Komut satırından (R --slave script.R) uzun bir R betiği çalıştırıyorsam, bunun hatalarda satır numaraları vermesini nasıl sağlayabilirim?

Mümkünse betiğe hata ayıklama komutları eklemek istemiyorum - sadece R'nin diğer birçok komut dosyası dili gibi davranmasını istiyorum ...


31
Herhangi bir güncelleme var mı? Dört yıl sonra, R.
Gui Ambros'un

Ayrıca çok sayıda küçük çıktı içeren çok uzun bir R betiğim var, satır numaralarını kodlamak yerine C'deki gibi yazdırmak (alt çizgi) (alt çizgi) SATIR / DOSYA (alt çizgi) (alt çizgi) (satır numaraları ve komut adı) istiyorum kaynağa.
mosh

R'nin dahili olarak gerçekten 'satır numaraları' nosyonuna sahip olup olmadığını bilmiyorum. Bununla birlikte, eksiksiz görevler, yani üst düzey görevler gibi bir kavram vardır. Örneğin, hangi üst düzey görevin başarısız olduğunu söylemek için bir görev işleyicisi kolayca tanımlanabilir. Elbette, bu büyük zincirlere veya büyük koşullu ifadelere sahip olanlar için büyük bir rahatlık değil.
russellpierce

Yanıtlar:


45

Bu size hat numarasını vermeyecektir, ancak çağrı yığınında arızanın nerede meydana geldiğini size söyleyecektir ki bu çok yararlıdır:

traceback()

[Düzenle:] Komut satırından bir komut dosyası çalıştırırken bir veya iki çağrıyı atlamanız gerekir, etkileşimli ve etkileşimli olmayan R oturumları için bkz. Traceback ()

Olağan hata ayıklama şüphelileri olmadan bunu yapmanın başka bir yolunu bilmiyorum:

  1. hata ayıklama ()
  2. tarayıcı ()
  3. seçenekler (hata = kurtarma) [ardından geri döndürmek için seçenekler (hata = NULL)]

Bu ilgili gönderiye bakmak isteyebilirsiniz.

[Düzenleme:] Üzgünüm ... az önce bunu komut satırından çalıştırdığınızı gördüm. Bu durumda, seçenekler (hata) işleviyle çalışmayı öneririm. İşte basit bir örnek:

options(error = quote({dump.frames(to.file=TRUE); q()}))

Bir hata durumunda istediğiniz kadar ayrıntılı bir komut dosyası oluşturabilirsiniz, bu nedenle hata ayıklama için hangi bilgilere ihtiyacınız olduğuna karar vermelisiniz.

Aksi takdirde, endişelendiğiniz belirli alanlar varsa (örneğin bir veritabanına bağlanmak), bunları bir tryCatch () işlevine sarın.


İlk [Düzenle:] bloğuna bağlanan çözüm benim için çalışıyor. En iyi yaklaşım @dsh Shepherd'ın yorumu gibi görünüyor, yani ekle options(error=function() { traceback(2); if(!interactive()) quit("no", status = 1, runLast = FALSE) })(kabul edilen cevabın yorumuna bakın). Bence sadece başka bir konu başlığına bağlantı sağlamaktansa, onu cevaba eklemek mantıklı olacaktır.
cryo111

1
satır numaralarını traceback github.com/aryoda/tryCatchLog
lunguini

13

Yapmak options(error=traceback), hataya yol açan satırların içeriği hakkında biraz daha bilgi sağlar. Bir hata varsa geri dönüşün görünmesine neden olur ve bazı hatalar için önünde satır numarası bulunur #. Ancak vurulur veya kaçırılır, birçok hata satır numaralarını almaz.


2
Benim için pek işe yaramıyor. Sadece bir dosyam var ve satır numarasını göstermiyor, sadece No traceback availablehatadan sonra diyor .
Mark Lakata

11

Bunun için destek R 2.10 ve sonrasında sunulacaktır. Duncan Murdoch, 10 Eylül 2009'da findLineNum ve setBreapoint hakkında r- devel'e bir mesaj gönderdi :

Hata ayıklamaya yardımcı olmak için R-devel'e birkaç işlev ekledim. findLineNum()hangi işlevin hangi satırının belirli bir kaynak kod satırına karşılık geldiğini bulur; setBreakpoint()çıkışını alır ve orada bir kesme noktası ayarlamayı findLineNumçağırır trace().

Bunlar, kodda kaynak referans hata ayıklama bilgilerine sahip olmaya dayanır. Bu, kod tarafından okunan varsayılan değerdir source(), ancak paketler için geçerli değildir. Kaynak referanslarını paket kodunda almak için ortam değişkenini ayarlayın R_KEEP_PKG_SOURCE=yesveya R içinde ayarlayın options(keep.source.pkgs=TRUE), ardından paketi kaynak kodundan yükleyin. ?findLineNumAramayı küresel ortamla sınırlamak yerine, paketler içinde arama yapmasının nasıl söyleneceği ile ilgili ayrıntılar için okuyun .

Örneğin,

x <- " f <- function(a, b) {
             if (a > b)  {
                 a
             } else {
                 b
             }
         }"


eval(parse(text=x))  # Normally you'd use source() to read a file...

findLineNum("<text>#3")   # <text> is a dummy filename used by
parse(text=)

Bu yazdıracak

 f step 2,3,2 in <environment: R_GlobalEnv>

ve kullanabilirsin

setBreakpoint("<text>#3")

orada bir kesme noktası ayarlamak için.

Kodda hala bazı sınırlamalar (ve muhtemelen hatalar) vardır; Ben bunları düzelteceğim


Teşekkürler. R-devel posta listesine de kaydoldum. Gelen kutumu tıkayacağı varsayımıyla r-help'den kaçınıyorum (r-sig-Finance bunu zaten yapıyor).
Shane

1
R betiğine bakmadan bunun komut satırından nasıl çalıştığını gerçekten anlamıyorum
Herman Toothrot,

1
@hirse: Bu neredeyse on eski cevabınız. Alıntı yapıyormuşum gibi yapmak için neden yeniden biçimlendirdin? Ben değildi ve paranızın üstü yok değil Niyetim yansıtmaktadır.
Dirk Eddelbuettel

"Duncan Murdoch az önce yayınladı:" bir alıntıya çok benziyor, ancak bu doğru değilse lütfen düzenlemeyi geri alın. Kendim için daha okunaklı hale getirmek istedim ve işim bitene kadar tarihi kontrol etmedim. Cevabın tamamı çok eski ise, gelecekteki okuyucuların kafa karışıklığını gidermek için cevabı da silebilirsiniz.
hirse

Lütfen geri döndürür müsün? Teşekkür ederim.
Dirk Eddelbuettel

6

Ayarlayarak yaparsın

options(show.error.locations = TRUE)

Sadece bu ayarın neden R'de varsayılan olmadığını merak ediyorum? Diğer her dilde olduğu gibi olması gerekir.


1
Bu seçenek hakkında arka plan bilgisi için stat.ethz.ch/R-manual/R-devel/library/base/html/options.html
R Yoda

1
Bu eskiden çalışıyordu, ancak güvenilir olmadığı için devre dışı bırakıldı. Bence bu, sizi sonunda özgür olmayacak olan RStudio'yu kullanmaya zorlama girişimi.
Eric Leschinski

6
Şüpheliyim. R çekirdeği ve RStudio çok farklı organizasyonlardır ve özellikle R çekirdeği sağlam açık kaynaklardır.
Ben Bolker

CentOS 6.9, R-3.4.2
irritable_phd_syndrom

Belki de bahsetmeye değer, herhangi bir kod sağlamadan önce seçenekleri önceden ayarlamalısınız.
JAponte

3

Benim için işe yarayan katastrofik olmayan hataları işlemek için global R seçeneğini belirtmek ve hatayla ilgili bilgileri saklamak ve hatadan sonra bu bilgileri incelemek için özelleştirilmiş bir iş akışı. Şu anda R 3.4.1 sürümünü çalıştırıyorum. Aşağıda, benim için çalışan iş akışının bir açıklamasının yanı sıra R'de genel hata işleme seçeneğini ayarlamak için kullandığım bazı kodları ekledim.

Yapılandırdığım gibi, hata işleme ayrıca hata anında çalışma belleğindeki tüm nesneleri içeren bir RData dosyası oluşturur. Bu döküm, kullanılarak R'ye geri okunabilir load()ve ardından, hata anında var olan çeşitli ortamlar kullanılarak etkileşimli olarak incelenebilir debugger(errorDump).

traceback()Yığın içindeki herhangi bir özel işlevden çıktıdaki satır numaralarını alabildiğimi , ancak yalnızca komut dizimde kullanılan herhangi bir özel işlevi keep.source=TRUEararken seçeneği source()kullandığımı not edeceğim. Bu seçenek olmadan, genel hata işleme seçeneğini aşağıdaki gibi ayarlamak, tam çıktısını traceback()adlı bir hata günlüğüne gönderdi error.log, ancak satır numaraları mevcut değildi.

İşte iş akışımda attığım genel adımlar ve etkileşimli olmayan bir R arızasından sonra bellek dökümü ve hata günlüğüne nasıl erişebildiğim.

  1. Komut satırından çağırdığım ana betiğin üstüne şunu koydum. Bu, R oturumu için genel hata işleme seçeneğini belirler. Ana senaryom çağrıldı myMainScript.R. Koddaki çeşitli satırlarda, yaptıkları şeyi açıklayan yorumlar vardır. Temel olarak, bu seçenekle, R tetikleyen bir hatayla karşılaştığında stop(), dizindeki tüm etkin ortamlarda çalışan belleğin RData (* .rda) döküm dosyasını oluşturur ~/myUsername/directoryForDumpve ayrıca error.logbazı yararlı bilgilerle adlandırılmış bir hata günlüğü de aynı dizin. Hata durumunda başka işlemler eklemek için bu parçacığı değiştirebilirsiniz (örneğin, döküm dosyasına bir zaman damgası ve hata günlüğü dosya adları vb. Ekleyin).

    options(error = quote({
      setwd('~/myUsername/directoryForDump'); # Set working directory where you want the dump to go, since dump.frames() doesn't seem to accept absolute file paths.
      dump.frames("errorDump", to.file=TRUE, include.GlobalEnv=TRUE); # First dump to file; this dump is not accessible by the R session.
      sink(file="error.log"); # Specify sink file to redirect all output.
      dump.frames(); # Dump again to be able to retrieve error message and write to error log; this dump is accessible by the R session since not dumped to file.
      cat(attr(last.dump,"error.message")); # Print error message to file, along with simplified stack trace.
      cat('\nTraceback:');
      cat('\n');
      traceback(2); # Print full traceback of function calls with all parameters. The 2 passed to traceback omits the outermost two function calls.
      sink();
      q()}))
  2. Ana komut dosyasından ve sonraki herhangi bir işlev çağrısından, bir işlev her kaynak alındığında, seçeneğin keep.source=TRUEkullanıldığından emin olun. Yani, bir işlevi kaynaklamak için kullanırsınız source('~/path/to/myFunction.R', keep.source=TRUE). Bu, traceback()çıktının satır numaralarını içermesi için gereklidir . Görünüşe göre bu seçeneği dünya çapında kullanarak da ayarlayabilirsiniz options( keep.source=TRUE ), ancak çalışıp çalışmadığını görmek için bunu test etmedim. Satır numaralarına ihtiyacınız yoksa, bu seçeneği atlayabilirsiniz.

  3. Terminalden (R dışında), kullanarak toplu iş modunda ana komut dosyasını çağırın Rscript myMainScript.R. Bu, etkileşimli olmayan yeni bir R oturumu başlatır ve komut dosyasını çalıştırır myMainScript.R. 1. adımda verilen kod parçacığı myMainScript.Retkileşimli olmayan R oturumu için hata işleme seçeneğini ayarlar.
  4. Uygulamasında bir yerde bir hatayla karşılaşın myMainScript.R. Bu, ana komut dosyasının kendisinde olabilir veya birkaç işlevi derinlemesine iç içe geçirebilir. Hata ile karşılaşıldığında, işlem 1. adımda belirtildiği gibi gerçekleştirilecek ve R oturumu sona erecektir.
  5. Genel hata işleme seçeneği ayarında tarafından belirtilen dizinde, adlı bir RData döküm dosyası errorDump.rdave adı ve hata günlüğü error.logoluşturulur '~/myUsername/directoryForDump'.
  6. Boş zamanlarınızda, error.loghata mesajının kendisi ve hataya yol açan tam yığın izleme dahil olmak üzere hatayla ilgili bilgileri gözden geçirmek için inceleyin . Hata oluştuğunda oluşturulan günlüğün bir örneğini burada bulabilirsiniz; #karakterden sonraki sayıların, çağrı yığınındaki çeşitli noktalardaki hatanın satır numaraları olduğuna dikkat edin:

    Error in callNonExistFunc() : could not find function "callNonExistFunc"
    Calls: test_multi_commodity_flow_cmd -> getExtendedConfigDF -> extendConfigDF
    
    Traceback:
    3: extendConfigDF(info_df, data_dir = user_dir, dlevel = dlevel) at test_multi_commodity_flow.R#304
    2: getExtendedConfigDF(config_file_path, out_dir, dlevel) at test_multi_commodity_flow.R#352
    1: test_multi_commodity_flow_cmd(config_file_path = config_file_path, 
    spot_file_path = spot_file_path, forward_file_path = forward_file_path, 
    data_dir = "../", user_dir = "Output", sim_type = "spot", 
    sim_scheme = "shape", sim_gran = "hourly", sim_adjust = "raw", 
    nsim = 5, start_date = "2017-07-01", end_date = "2017-12-31", 
    compute_averages = opt$compute_averages, compute_shapes = opt$compute_shapes, 
    overwrite = opt$overwrite, nmonths = opt$nmonths, forward_regime = opt$fregime, 
    ltfv_ratio = opt$ltfv_ratio, method = opt$method, dlevel = 0)
  7. Boş zamanlarınızda, errorDump.rdakullanarak etkileşimli bir R oturumuna yükleyebilirsiniz load('~/path/to/errorDump.rda'). Yüklendikten sonra, debugger(errorDump)herhangi bir aktif ortamdaki bellekteki tüm R nesnelerine göz atmak için çağrı yapın. Daha debugger()fazla bilgi için R yardımına bakın .

Bu iş akışı, komut satırında başlatılan etkileşimli olmayan R oturumlarının olduğu ve beklenmeyen hatalarla ilgili bilgilerin saklanmasını istediğiniz bazı üretim ortamında R çalıştırırken son derece yararlıdır. Arama yığınındaki hatanın satır numaralarına sahip olmanın yanı sıra, hata anında çalışma belleğini incelemek için kullanabileceğiniz bir dosyaya bellek boşaltma yeteneği, hataya neyin neden olduğu konusunda hızlı ölüm sonrası hata ayıklamayı kolaylaştırır.


0

Önce options(show.error.locations = TRUE)ve sonra traceback(). # Sonra hata satırı numarası görüntülenecektir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.