8次发布
0.5.7 | 2023年7月6日 |
---|---|
0.5.6 | 2023年6月26日 |
0.5.5 | 2022年9月16日 |
0.5.4 | 2021年12月4日 |
0.5.0 | 2020年6月3日 |
#147 in 过程宏
每月 62 次下载
5KB
inline-python
在Rust代码中直接嵌入Python代码。
示例
use inline_python::python;
fn main() {
let who = "world";
let n = 5;
python! {
for i in range('n):
print(i, "Hello", 'who)
print("Goodbye")
}
}
如何使用
使用python!{..}
宏,直接在Rust代码中编写Python代码。
注意:需要Rust nightly工具链。功能proc_macro_span
仍处于不稳定状态,更多详情请查看问题#54725 - proc_macro::Span
检查API的跟踪问题
使用Rust变量
要引用Rust变量,使用'var
,如上例所示。 var
需要实现pyo3::ToPyObject
。
重用Python上下文
可以在运行Python代码之前创建一个Context
对象,并使用它来运行Python代码。上下文可以被重用多次调用,以在宏调用之间共享全局变量。
let c = Context::new();
c.run(python! {
foo = 5
});
c.run(python! {
assert foo == 5
});
作为一个快捷方式,你可以直接将一个python!{}
调用赋值给一个类型为Context
的变量,以创建一个新的上下文并在其中运行Python代码。
let c: Context = python! {
foo = 5
};
c.run(python! {
assert foo == 5
});
获取信息回传
Context
对象还可以用来将信息传回Rust,因为你可以通过Context::get
从上下文中检索全局Python变量。
let c: Context = python! {
foo = 5
};
assert_eq!(c.get::<i32>("foo"), 5);
语法问题
由于Rust标记器会对Python代码进行标记,一些有效的Python代码被拒绝。需要记住的两件事是
-
使用双引号字符串(
""
)而不是单引号字符串(''
)。(单引号字符串仅当它们包含单个字符时才有效,因为在Rust中,
'a'
是一个字符字面量。) -
使用
//
注释而不是#
注释。(如果您使用
#
注释,Rust标记器会尝试对您的注释进行标记,如果您的注释没有正确标记,则会报错。)
其他一些不起作用的小问题是
-
字符串字面量中的某些转义码。(特别是:
\a
,\b
,\f
,\v
,\N
(以大括号表示的范围),\123
(八进制转义码),\u
,和\U
。)然而,这些都可以正常接受:
\\
,\n
,\t
,\r
,\xAB
(十六进制转义码),和\0
-
带有转义双引号的原始字符串字面量。(例如:
r"..."..."
。) -
不作为常规字符串有效的内容的三重引号字节和原始字符串。以及相同的原始字节和原始格式字符串。(例如:
b"""\xFF"""
,r"\z"
,fr"\z"
,br"\xFF"
。) -
由于它们会开始一个注释,
//
和//=
操作符不可用。解决方案:您可以用
##
代替,它会自动转换为//
。
其他一切应该都能正常工作。
lib.rs
:
在编译时执行Python代码以生成Rust代码。
示例
use ct_python::ct_python;
static SIN_2: f64 = ct_python! {
from math import sin
print(sin(2))
};
ct_python! {
print("type num = f64;")
}
fn main() {
assert_eq!(num::sin(2.0), SIN_2);
}
如何使用
使用ct_python!{..}
宏从嵌入的Python脚本中生成Rust代码。脚本的输出(print()
和通过sys.stdout
的其他内容)被捕获,并将被解析为Rust代码。
Python 错误
Python代码中的任何语法错误或运行时异常都将由Rust编译器报告为编译器错误。
语法问题
由于Rust分词器会解析Python代码,一些有效的Python代码可能会被拒绝。有关详细信息,请参阅《inline-python
》文档。
依赖项
~2.5–8MB
~55K SLoC