错误处理
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 与编辑器支持 — 语言服务器功能