又到了 kaopubear 的專欄時間,本文較長圖多,真誠建議滑到文末 閱讀原文 體驗更加。閱讀更多內容,也歡迎 閱讀原文 移步我的博客。 第一次接觸網頁開發(fā)是兩三年前的事,那時我曾經問過計劃帶我入門前端的前輩:入門前端的標準是什么。他當時用一種極平和的語氣和我說:學會dubug。幾年后的今天我即便也寫過一點網頁工具,但還是依然沒能入門。反思一下:一是 JavaScript 學的不好,二就是不敢說自己有多少 debug 的能力。 遂放棄。 最近因為需要又要涉及一點網頁工具開發(fā),同時因為需求整體和 R 交互比較多于是決定用 R 的 Shiny 來搞一搞。 寫了一個多星期我感覺 Shiny 確實解決了不熟悉前后端交互的人寫網頁的大多數(shù)問題,但如何 debug 的門檻還是擺在那里。比如前幾天一個高手和我吐槽寫 Shiny 時不知道改了什么突然不能正確運行了,更糟心的是還沒有任何報錯信息。當然,后來經過討論發(fā)現(xiàn)其實并非沒有報錯信息,只是那時他沒有找到而已。 這篇文章就結合最近學習的一點資料,大致聊聊在 Shiny 中 debug 的一些方法。 Shiny debug 主要有三個步驟,分別是調試(Debugging),追蹤(Tracing)和錯誤處理(Error handling)。
Debugging 調試breakpoints 斷點說到「斷點」,我不由的想對 bug 說一句:
如果你知道哪一行的代碼有錯(這話本身就像bug)或者猜測很可能是哪里不對,就可以直接在所在行設置一個斷點。Rstudio 只需在行號左邊點一下鼠標就會出現(xiàn)紅點提示標記成功。開始運行 Shiny 程序后會在斷點處停止執(zhí)行,然后就可以開始逐步執(zhí)行進行代碼調試了。 如上圖所示,我們在 40 和 41 行設置了兩個斷點,現(xiàn)在點擊 這個時候我們可以方便的查看環(huán)境中已有的變量,例如這里已經運行完畢的 現(xiàn)在環(huán)境中存在 x 和 bin 兩個變量,同時在 console 的 說到缺點,目前 breakpoints 只可以在 Rstudio IDE 中使用,而且只能用于 小結如下: browser() 命令其實從上面 console 的截圖也可以看到,斷點就是執(zhí)行了一次類
甚至你還可以把 小結如下 Tracing 追蹤在許多情況下通過暫停執(zhí)行來找問題比較困難,相反需要我們在程序運行時觀察系統(tǒng)。對于 Shiny 的程序尤其如此,因為他不像 R 腳本那樣線性運行。 Showcase ModeShiny 在啟動時, 如果想要默認開啟這一功能,可以在該 Shiny 目錄下創(chuàng)建一個 DisplayMode: Showcase小結如下 ![]() Reactive Log在 Shiny 中經常會用到響應對象,當開啟 Reactive Log 之后,程序運行時除了可以告訴你正在執(zhí)行哪些響應之外,日志還可以幫助你可視化展示響應對象之間的依賴關系。在開啟一個新的 R session 時首先配置 ![]() 打印 tracing在各種編程語言中,一個萬變不離其宗的調試技巧就是不停的輸出。在 PHP 里面是不停的 進行上述修改后,運行 Shiny 每次調整 input 都會在 console 中打印輸出。如下圖所示 ![]() 小結如下 ![]() Shiny Server 進行 tracing如果你的程序運行在 server 端而非本地,每次 Shiny 程序運行都會生成 log 文件,默認的路徑是 客戶端和服務器端 Tracing一個 Shiny 程序包括 client (瀏覽器) 和 server (R 進程) 兩部分。這兩者通過 websocket連接,websocket 接收來自客戶端的狀態(tài),例如輸入控件新的賦值,同時發(fā)布來自服務器端的狀態(tài)更改,例如新的輸出。在一些比較復雜的情況下,你可以通過打開 trace 來跟蹤 JSON 格式的 websocket 內容。 ![]() 如上圖所示,在輸出內容中,
Errors 錯誤跑程序最怕看到的就是報錯,但是真要有問題了最希望看到的就是明確的報錯。 R 報錯在 Shiny 中大多數(shù)報錯信息都是由R引起的,在 0.13.0 之后的 Shiny 版本中已經有了比較直觀的報錯形式,會直接給出哪里的程序出現(xiàn)了錯誤。這里首先人為引入一個報錯,當 input 大于 40 的時候停止程序并且拋出 ![]() 運行程序后調整輸入如果錯誤,可以觀察 console 的輸出內容: ![]() 首先直接觀察顏色不同的部分,直接告訴我們 JavaScript errors目前 Shiny 有很多第三方 JavaScript 組件,有時如果使用上面幾種方式都沒有定位到錯誤相關問題或者沒有看到報錯信息,很可能是 JavaScript 中發(fā)生錯誤導致程序出現(xiàn)了bug。畢竟 Shiny 是個網頁應用,各種和用戶的交互少不了 JavaScript 的使用。 要進行 JavaScript 的調試在 Rstudio 就不靈了。如果你是通過 Rstudio 打開了一個單獨 Shiny 頁面,可以通過右鍵單擊 Shiny頁面,選擇 ![]() 在 Shiny 中 UI 的每個部分都會有一個 id 參數(shù),這個 id 對應的參數(shù)在瀏覽器中解析之后就是對應著 HTML 標簽中的 id。在 HTML 中,這個 id 是必須唯一(區(qū)別于name)。因此,在Shiny的ui中每一個id參數(shù)也必須唯一。解析效果如下圖所示: ![]() 如果你不小心在 UI 中寫入了兩個一樣的 id,在上圖中就有兩個標簽的 id 都是 a,程序運行后在 Rstudio 并不會拋出什么錯誤,但是在 Shiny 頁面端的各種操作就進行不了。如果不在開發(fā)者模式下進行調試只能通過各種方法在 Rstudio 進行測試,但是如果打開 JavaScript 的 console,就會看到其實已經給出了明確的報錯信息。 ![]() 當然,Chrome 開發(fā)者工具的用法是在太多,這也是我在文章開頭提到的自己入門不了前端的原因之一。如果在你的 Shiny 中用到了大量 JavaScript 相關內容,或者需要定制很多 CSS 相關的內容,可以學習一下官方的開發(fā)者工具文檔。 至此,也就簡單的寫完了 R Shiny debug 的三個主要步驟,其中提到的每一個用法在實際使用中都需要進一步深入學習。當然,每一個方法用到的頻率也各有不同,可以根據個人的實際情況進行后續(xù)的練習。 One more thing:shinyjs寫到這里本來文章就可以結束了,但是似乎總有哪里不對。 為什么在 Rstudio 的 console 里就不能查看 JavaScript 的 log 信息。要知道 Rstudio GUI 本身使用的就是 QT框架,其中的很多部分都可以理解為一個網頁。從維基百科或者它自己的說明中都可以看出這一點。 ![]() ![]() 不信的話你也可以在 Rstuido 的每個 pane 里右擊然后選擇 ![]() 你會看到下面圖所示的內容 ![]() 既然如此,沒有理由不去解決這個不方便的問題。其實在 R 中有一個專門為 Shiny 提高 JavaScript 使用體驗開發(fā)的R包,叫做shinyjs。這個包的存在讓 Shiny 使用 JavaScript 變得強大和高效了很多。其中針對調試有兩個專門的函數(shù)。 showLog
這個函數(shù)類似于 JavaScript 中的 logjs
這個函數(shù)則可以把信息輸出到 JavaScript console 中方便進行調試。 例如下面一段代碼: library(ShinyJavaScript)運行后通過點擊 button ,就可以把 ![]() 嗯,先寫到這里吧。 我的學習材料
|
|
|