乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      給你的 R Shiny debug 必看指南

       微笑如酒 2019-04-13

      Finding your bug is a process of confirming the many things that you believe are true — until you find one which is not true.

      —Norm Matloff

      又到了 kaopubear 的專(zhuān)欄時(shí)間,本文較長(zhǎng)圖多,真誠(chéng)建議滑到文末 閱讀原文 體驗(yàn)更加。閱讀更多內(nèi)容,也歡迎 閱讀原文 移步我的博客。


      第一次接觸網(wǎng)頁(yè)開(kāi)發(fā)是兩三年前的事,那時(shí)我曾經(jīng)問(wèn)過(guò)計(jì)劃帶我入門(mén)前端的前輩:入門(mén)前端的標(biāo)準(zhǔn)是什么。他當(dāng)時(shí)用一種極平和的語(yǔ)氣和我說(shuō):學(xué)會(huì)dubug。幾年后的今天我即便也寫(xiě)過(guò)一點(diǎn)網(wǎng)頁(yè)工具,但還是依然沒(méi)能入門(mén)。反思一下:一是 JavaScript 學(xué)的不好,二就是不敢說(shuō)自己有多少 debug 的能力。

      遂放棄。

      最近因?yàn)樾枰忠婕耙稽c(diǎn)網(wǎng)頁(yè)工具開(kāi)發(fā),同時(shí)因?yàn)樾枨笳w和 R 交互比較多于是決定用 R 的 Shiny 來(lái)搞一搞。

      寫(xiě)了一個(gè)多星期我感覺(jué) Shiny 確實(shí)解決了不熟悉前后端交互的人寫(xiě)網(wǎng)頁(yè)的大多數(shù)問(wèn)題,但如何 debug 的門(mén)檻還是擺在那里。比如前幾天一個(gè)高手和我吐槽寫(xiě) Shiny 時(shí)不知道改了什么突然不能正確運(yùn)行了,更糟心的是還沒(méi)有任何報(bào)錯(cuò)信息。當(dāng)然,后來(lái)經(jīng)過(guò)討論發(fā)現(xiàn)其實(shí)并非沒(méi)有報(bào)錯(cuò)信息,只是那時(shí)他沒(méi)有找到而已。

      這篇文章就結(jié)合最近學(xué)習(xí)的一點(diǎn)資料,大致聊聊在 Shiny 中 debug 的一些方法。

      Shiny debug 主要有三個(gè)步驟,分別是調(diào)試(Debugging),追蹤(Tracing)和錯(cuò)誤處理(Error handling)。

      • Debugging: 所謂的調(diào)試就是猜,然后在你認(rèn)為可能有錯(cuò)誤的地方設(shè)置一個(gè)斷點(diǎn),再執(zhí)行接下來(lái)每個(gè)語(yǔ)句的時(shí)候就都可以檢查程序當(dāng)時(shí)所在的狀態(tài)。

      • Tracing:可以在運(yùn)行程序的時(shí)候收集程序運(yùn)行產(chǎn)生的信息而無(wú)需暫停程序,在診斷系統(tǒng)性問(wèn)題時(shí)因?yàn)槲覀儫o(wú)法頻繁的中斷使用這一方式就比較合適。

      • Error handling: 在客戶(hù)端和服務(wù)器端找到錯(cuò)誤的來(lái)源并確定原因。

      Debugging 調(diào)試

      breakpoints 斷點(diǎn)

      說(shuō)到「斷點(diǎn)」,我不由的想對(duì) bug 說(shuō)一句:

      靜靜地陪你走了好遠(yuǎn)好遠(yuǎn),連眼睛紅了都沒(méi)有發(fā)現(xiàn)。

      如果你知道哪一行的代碼有錯(cuò)(這話本身就像bug)或者猜測(cè)很可能是哪里不對(duì),就可以直接在所在行設(shè)置一個(gè)斷點(diǎn)。Rstudio 只需在行號(hào)左邊點(diǎn)一下鼠標(biāo)就會(huì)出現(xiàn)紅點(diǎn)提示標(biāo)記成功。開(kāi)始運(yùn)行 Shiny 程序后會(huì)在斷點(diǎn)處停止執(zhí)行,然后就可以開(kāi)始逐步執(zhí)行進(jìn)行代碼調(diào)試了。

      如上圖所示,我們?cè)?40 和 41 行設(shè)置了兩個(gè)斷點(diǎn),現(xiàn)在點(diǎn)擊 Run App,代碼運(yùn)行會(huì)在 40 行處停下,綠色的箭頭指向 41 行,并且在 console 中會(huì)有 browse輸出,如下圖所示

      這個(gè)時(shí)候我們可以方便的查看環(huán)境中已有的變量,例如這里已經(jīng)運(yùn)行完畢的 x 變量。如果想繼續(xù)運(yùn)行,可以點(diǎn)擊 console 里的 continue,程序又會(huì)向下運(yùn)行。

      現(xiàn)在環(huán)境中存在 x 和 bin 兩個(gè)變量,同時(shí)在 console 的 browse[2]> 處你可以進(jìn)行正常的 R 操作,例如查看變量?jī)?nèi)容或者做個(gè)加法運(yùn)算,甚至你可以修改當(dāng)前存在環(huán)境中的變量(當(dāng)然不推薦這么操作)。

      說(shuō)到缺點(diǎn),目前 breakpoints 只可以在 Rstudio IDE 中使用,而且只能用于ShinyServer函數(shù)中;另外如果代碼很長(zhǎng)顯然不停的斷點(diǎn)也很煩,同時(shí)它只能顯示發(fā)生了什么但是無(wú)法告訴你為什么有些事情沒(méi)有發(fā)生。

      小結(jié)如下:

      browser() 命令

      其實(shí)從上面 console 的截圖也可以看到,斷點(diǎn)就是執(zhí)行了一次類(lèi) browser() 操作。但和斷點(diǎn)不同的是,browser() 本身可以被寫(xiě)到任何地方。寫(xiě)法如下圖所示:

      說(shuō)明:你現(xiàn)在從簡(jiǎn)書(shū)看到的為本文的付費(fèi)版本,如果需要可以付費(fèi)繼續(xù)閱讀。當(dāng)然,完整的文章可以在我的個(gè)人博客免費(fèi)閱讀,歡迎繼續(xù)查看。

      甚至你還可以把 browser() 寫(xiě)進(jìn)判斷語(yǔ)句中,只在某些特定的情況下執(zhí)行。例如下圖所示,在 input 中的 bins 小于 40 時(shí)候程序會(huì)正常的執(zhí)行,當(dāng)大于 40時(shí)才會(huì)自動(dòng)停下,然后你就可以在調(diào)試器中查看具體的變量等信息。

      小結(jié)如下

      Tracing 追蹤

      在許多情況下通過(guò)暫停執(zhí)行來(lái)找問(wèn)題比較困難,相反需要我們?cè)诔绦蜻\(yùn)行時(shí)觀察系統(tǒng)。對(duì)于 Shiny 的程序尤其如此,因?yàn)樗幌?nbsp;R 腳本那樣線性運(yùn)行。

      Showcase Mode

      Shiny 在啟動(dòng)時(shí),runAPP() 有一個(gè)選項(xiàng)默認(rèn)是讀取配置文件中的設(shè)置,它就是 display.mode。如果我們?cè)O(shè)置為display.mode='showcase',在 Showcase 模式下,代碼將與應(yīng)用程序一起顯示,并且程序的 server 端代碼在執(zhí)行時(shí)會(huì)出現(xiàn)黃色的閃爍進(jìn)行提醒。這一功能對(duì)于可視化哪些部分代碼正在執(zhí)行非常有用。

      如果想要默認(rèn)開(kāi)啟這一功能,可以在該 Shiny 目錄下創(chuàng)建一個(gè) DESCRIPTION 文件并寫(xiě)入如下內(nèi)容:

      DisplayMode: Showcase
      Type: Shiny

      小結(jié)如下

      Reactive Log

      在 Shiny 中經(jīng)常會(huì)用到響應(yīng)對(duì)象,當(dāng)開(kāi)啟 Reactive Log 之后,程序運(yùn)行時(shí)除了可以告訴你正在執(zhí)行哪些響應(yīng)之外,日志還可以幫助你可視化展示響應(yīng)對(duì)象之間的依賴(lài)關(guān)系。在開(kāi)啟一個(gè)新的 R session 時(shí)首先配置 options(Shiny.reactlog=TRUE),然后在 Shiny app 中通過(guò) Ctrl + F3 就可以啟動(dòng)可視化的 Reactive Log 文件,也可以在運(yùn)行Shiny 后使用 showReactLog 查看。詳細(xì)信息可以在 官方文檔 了解。

      打印 tracing

      在各種編程語(yǔ)言中,一個(gè)萬(wàn)變不離其宗的調(diào)試技巧就是不停的輸出。在 PHP 里面是不停的 echo,在 R 里可以不停的 cat。使用 cat 可以幫助你在不終止程序的情況下查看變量值。在 Shiny 中,最好的方式是打印標(biāo)準(zhǔn)錯(cuò)誤(stderr())。

      # generate bins based on input$bins from ui.R
      x    <- faithful[, 2
      bins <- seq(min(x), max(x), length.out = input$bins + 1)
      cat(file=stderr(), 'drawing histogram with', input$bins, 'bins''\n')

      進(jìn)行上述修改后,運(yùn)行 Shiny 每次調(diào)整 input 都會(huì)在 console 中打印輸出。如下圖所示

      小結(jié)如下

      Shiny Server 進(jìn)行 tracing

      如果你的程序運(yùn)行在 server 端而非本地,每次 Shiny 程序運(yùn)行都會(huì)生成 log 文件,默認(rèn)的路徑是 /var/log/Shiny-server/*.log,而這一位置是可以在配置文件中通過(guò)log_dir進(jìn)行修改的。如果程序運(yùn)行沒(méi)有出現(xiàn)問(wèn)題,每次 Shiny 運(yùn)行結(jié)束后文件會(huì)自動(dòng)刪除,如果報(bào)錯(cuò)了則會(huì)一直存在于 log 目錄等你去寵幸。log 文件的命名格式為<application directory name>-YYYMMDD-HHmmss-<port number or socket ID>.log 。

      客戶(hù)端和服務(wù)器端 Tracing

      一個(gè) Shiny 程序包括 client (瀏覽器) 和 server (R 進(jìn)程) 兩部分。這兩者通過(guò) websocket連接,websocket 接收來(lái)自客戶(hù)端的狀態(tài),例如輸入控件新的賦值,同時(shí)發(fā)布來(lái)自服務(wù)器端的狀態(tài)更改,例如新的輸出。在一些比較復(fù)雜的情況下,你可以通過(guò)打開(kāi) trace 來(lái)跟蹤 JSON 格式的 websocket 內(nèi)容。

      如上圖所示,在輸出內(nèi)容中,SEND 表示從瀏覽器發(fā)送到 R session 的數(shù)據(jù);RECV 表示從 R session 發(fā)送到瀏覽器的數(shù)據(jù)。

      這一部分目前還沒(méi)有實(shí)際用到,理解到位了可以再寫(xiě)一些。

      Errors 錯(cuò)誤

      跑程序最怕看到的就是報(bào)錯(cuò),但是真要有問(wèn)題了最希望看到的就是明確的報(bào)錯(cuò)。

      R 報(bào)錯(cuò)

      在 Shiny 中大多數(shù)報(bào)錯(cuò)信息都是由R引起的,在 0.13.0 之后的 Shiny 版本中已經(jīng)有了比較直觀的報(bào)錯(cuò)形式,會(huì)直接給出哪里的程序出現(xiàn)了錯(cuò)誤。這里首先人為引入一個(gè)報(bào)錯(cuò),當(dāng) input 大于 40 的時(shí)候停止程序并且拋出 too many bins 的報(bào)錯(cuò)信息。

      運(yùn)行程序后調(diào)整輸入如果錯(cuò)誤,可以觀察 console 的輸出內(nèi)容:

      首先直接觀察顏色不同的部分,直接告訴我們 app.R 的 43 行代碼出現(xiàn)了問(wèn)題。在報(bào)錯(cuò)部分,每一行內(nèi)容前都有一個(gè)數(shù)字,例如1,82,165和167,其表示的是在調(diào)用棧(call stack)中的索引,可以看到這個(gè)例子中有接近170個(gè)調(diào)用棧。

      JavaScript errors

      目前 Shiny 有很多第三方 JavaScript 組件,有時(shí)如果使用上面幾種方式都沒(méi)有定位到錯(cuò)誤相關(guān)問(wèn)題或者沒(méi)有看到報(bào)錯(cuò)信息,很可能是 JavaScript 中發(fā)生錯(cuò)誤導(dǎo)致程序出現(xiàn)了bug。畢竟 Shiny 是個(gè)網(wǎng)頁(yè)應(yīng)用,各種和用戶(hù)的交互少不了 JavaScript 的使用。

      要進(jìn)行 JavaScript 的調(diào)試在 Rstudio 就不靈了。如果你是通過(guò) Rstudio 打開(kāi)了一個(gè)單獨(dú) Shiny 頁(yè)面,可以通過(guò)右鍵單擊 Shiny頁(yè)面,選擇Inspect element 進(jìn)入 JavaScript console;如果你的 Shiny 頁(yè)面是open in browser,也就是在瀏覽器中打開(kāi)的,可以直接通過(guò)F12進(jìn)入開(kāi)發(fā)者模式打開(kāi) JavaScript console 。

      在 Shiny 中 UI 的每個(gè)部分都會(huì)有一個(gè) id 參數(shù),這個(gè) id 對(duì)應(yīng)的參數(shù)在瀏覽器中解析之后就是對(duì)應(yīng)著 HTML 標(biāo)簽中的 id。在 HTML 中,這個(gè) id 是必須唯一(區(qū)別于name)。因此,在Shiny的ui中每一個(gè)id參數(shù)也必須唯一。解析效果如下圖所示:

      如果你不小心在 UI 中寫(xiě)入了兩個(gè)一樣的 id,在上圖中就有兩個(gè)標(biāo)簽的 id 都是 a,程序運(yùn)行后在 Rstudio 并不會(huì)拋出什么錯(cuò)誤,但是在 Shiny 頁(yè)面端的各種操作就進(jìn)行不了。如果不在開(kāi)發(fā)者模式下進(jìn)行調(diào)試只能通過(guò)各種方法在 Rstudio 進(jìn)行測(cè)試,但是如果打開(kāi) JavaScript 的 console,就會(huì)看到其實(shí)已經(jīng)給出了明確的報(bào)錯(cuò)信息。

      當(dāng)然,Chrome 開(kāi)發(fā)者工具的用法是在太多,這也是我在文章開(kāi)頭提到的自己入門(mén)不了前端的原因之一。如果在你的 Shiny 中用到了大量 JavaScript 相關(guān)內(nèi)容,或者需要定制很多 CSS 相關(guān)的內(nèi)容,可以學(xué)習(xí)一下官方的開(kāi)發(fā)者工具文檔。

      至此,也就簡(jiǎn)單的寫(xiě)完了 R Shiny debug 的三個(gè)主要步驟,其中提到的每一個(gè)用法在實(shí)際使用中都需要進(jìn)一步深入學(xué)習(xí)。當(dāng)然,每一個(gè)方法用到的頻率也各有不同,可以根據(jù)個(gè)人的實(shí)際情況進(jìn)行后續(xù)的練習(xí)。

      One more thing:shinyjs

      寫(xiě)到這里本來(lái)文章就可以結(jié)束了,但是似乎總有哪里不對(duì)。

      為什么在 Rstudio 的 console 里就不能查看 JavaScript 的 log 信息。要知道 Rstudio GUI 本身使用的就是 QT框架,其中的很多部分都可以理解為一個(gè)網(wǎng)頁(yè)。從維基百科或者它自己的說(shuō)明中都可以看出這一點(diǎn)。

      不信的話你也可以在 Rstuido 的每個(gè) pane 里右擊然后選擇Inspect element看看會(huì)出現(xiàn)什么,比如在 Console 中右擊

      你會(huì)看到下面圖所示的內(nèi)容

      既然如此,沒(méi)有理由不去解決這個(gè)不方便的問(wèn)題。其實(shí)在 R 中有一個(gè)專(zhuān)門(mén)為 Shiny 提高 JavaScript 使用體驗(yàn)開(kāi)發(fā)的R包,叫做shinyjs。這個(gè)包的存在讓 Shiny 使用 JavaScript 變得強(qiáng)大和高效了很多。其中針對(duì)調(diào)試有兩個(gè)專(zhuān)門(mén)的函數(shù)。

      showLog

      Print any JavaScript console.log() messages in the R console, to make it easier and quicker to debug apps without having to open the JavaScript console.

      這個(gè)函數(shù)類(lèi)似于 JavaScript 中的console.log(),它可以把 JavaScript console 的信息顯示在R console 中而不需要再打開(kāi)專(zhuān)門(mén)的 JavaScript console。

      logjs

      Print a message to the JavaScript console (mainly used for debugging purposes).

      這個(gè)函數(shù)則可以把信息輸出到 JavaScript console 中方便進(jìn)行調(diào)試。

      例如下面一段代碼:

      library(ShinyJavaScript)

      if (interactive()) {
          library(Shiny)
          ShinyApp(
              ui = fluidPage(
                  useShinyJavaScript(),  # Set up ShinyJavaScript
                  actionButton('btn''Click me')
              ),
              server = function(input, output) {
                  observeEvent(input$btn, {
                      # Change the following line for more examples
                      logJavaScript(R.Version())
                  })
              }
          )
      }

      運(yùn)行后通過(guò)點(diǎn)擊 button ,就可以把 R.Vsrsion() 的信息輸出到 JavaScript console 中,如下圖所示:


      嗯,先寫(xiě)到這里吧。

      我的學(xué)習(xí)材料

      • Chrome開(kāi)發(fā)者工具

      • Debugging Shiny applications

      • Debugging with RStudio

      • shinyjs



        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多