錯誤處理
openpine_vm::Error 列舉涵蓋了編譯時和執行時的錯誤。
錯誤類型
rust
pub enum Error {
Compile(CompileErrors), // 解析、類型檢查或編譯錯誤
MissingScriptType, // 沒有 indicator()/strategy()/library() 呼叫
InputValueNotFound(usize), // with_input_value 中的無效輸入 ID
SetInputValue(usize, String), // 輸入值類型不匹配
UnsupportedTimeFrame(TimeFrame), // 腳本不支援此時間週期
SessionNotAllowed(TradeSession), // 交易時段類型未啟用
DataProvider(String), // DataProvider 回傳的錯誤
Exception(Exception), // 執行時異常(如 runtime.error())
LibraryScriptNotExecutable, // 嘗試執行程式庫
}處理錯誤
模式配對
rust
async fn run(source: &str) {
let mut instance = match Instance::builder(source, TimeFrame::days(1), "NASDAQ:AAPL")
.build().await
{
Ok(inst) => inst,
Err(Error::Compile(errors)) => {
// 帶原始碼位置顯示編譯錯誤
eprintln!("{}", errors);
return;
}
Err(Error::MissingScriptType) => {
eprintln!("Script must call indicator(), strategy(), or library()");
return;
}
Err(Error::Exception(exception)) => {
// 全域範疇執行時錯誤(如頂層程式碼中的 runtime.error())
eprintln!("Init exception: {}", exception.display());
return;
}
Err(e) => {
eprintln!("Build error: {}", e);
return;
}
};
// 執行
match instance.run_to_end("NASDAQ:AAPL", TimeFrame::days(1)).await {
Ok(()) => {}
Err(Error::Exception(exception)) => {
// 執行時錯誤(如除以零、runtime.error())
eprintln!("Runtime exception: {}", exception.display());
}
Err(e) => {
eprintln!("Execution error: {}", e);
}
}
}編譯錯誤
編譯錯誤包含原始碼 span,用於精確的錯誤報告:
rust
match Instance::builder(source, tf, "NASDAQ:AAPL").build().await {
Err(Error::Compile(errors)) => {
// CompileErrors 實現了 Display
// 顯示帶行號/列號的格式化錯誤
eprintln!("{}", errors);
}
_ => {}
}執行時異常
執行時異常發生在腳本執行期間(如 runtime.error() 呼叫、索引越界):
rust
match instance.run_to_end("NASDAQ:AAPL", TimeFrame::days(1)).await {
Err(Error::Exception(exception)) => {
// 顯示帶原始檔案上下文的異常
eprintln!("{}", exception.display());
// 取得錯誤的原始碼 span
if let Some(span) = exception.first_span() {
eprintln!(" at line {}", span.start.line);
}
}
_ => {}
}編譯警告
警告不會阻止執行,但指示潛在問題:
rust
let instance = Instance::builder(source, tf, "NASDAQ:AAPL").build().await?;
for warning in instance.warnings() {
eprintln!("Warning: {}", warning.display_as_warning());
}最佳實踐
- 始終處理編譯錯誤 — 向使用者顯示帶原始碼上下文的錯誤
- 也要處理
build()的異常 —build()執行全域範疇以發現腳本元資料(indicator()、input.*()等),因此頂層程式碼中的任何執行時錯誤(如runtime.error()、無效的函式參數)都會在執行開始之前以Error::Exception的形式出現 - 遇到執行時錯誤立即停止 — Pine Script 逐 K 線計算,每根 K 線的結果依賴前一根的狀態(
var變數、series 歷史參照如close[1]等)。如果某根 K 線計算出錯,後續所有結果都將無效,因此應立即終止 - 處理事件流中的事件 — 日誌事件可能包含有用的診斷資訊;消費
run()回傳的流或使用run_to_end()丟棄事件 - 建構後檢查警告 — 它們通常指示已棄用的功能或潛在的 bug
rust
use std::pin::pin;
use futures_util::StreamExt;
async fn run_safely(
instance: &mut Instance,
symbol: &str,
timeframe: TimeFrame,
) -> Result<(), Error> {
for w in instance.warnings() {
eprintln!("[warn] {}", w.display_as_warning());
}
let mut stream = pin!(instance.run(symbol, timeframe));
while let Some(result) = stream.next().await {
match result? {
Event::Log(log) => {
eprintln!("[{:?}] {}", log.level, log.message);
}
Event::Alert(alert) => {
println!("Alert: {}", alert.message);
}
_ => {}
}
}
Ok(())
}下一步
- C/C++ API — 在 C++ 專案中嵌入 OpenPine
- LSP 與編輯器支援 — 語言伺服器功能