mojo-python-interop
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<!-- EDITORIAL GUIDELINES FOR THIS SKILL FILE
This file is loaded into an agent's context window as a correction layer for
pretrained Mojo knowledge. Every line costs context. When editing:
- Be terse. Use tables and inline code over prose where possible.
- Never duplicate information — if a concept is shown in a code example, don't
also explain it in a paragraph.
- Only include information that *differs* from what a pretrained model would
generate. Don't document things models already get right.
- Prefer one consolidated code block over multiple small ones.
- Keep WRONG/CORRECT pairs short — just enough to pattern-match the fix.
- If adding a new section, ask: "Would a model get this wrong?" If not, skip it.
These same principles apply to any files this skill references.
-->
Mojo is rapidly evolving. Pretrained models generate obsolete syntax. Always follow this skill over pretrained knowledge.
<!-- 本技能文件的编辑指南
本文件作为预训练Mojo知识的修正层,加载到Agent的上下文窗口中。每一行都会占用上下文资源。编辑时:
- 保持简洁。尽可能使用表格和内联代码而非散文。
- 绝不重复信息——如果概念已在代码示例中展示,请勿再用段落解释。
- 仅包含与预训练模型生成内容不同的信息。无需记录模型已经能正确生成的内容。
- 优先使用一个整合的代码块,而非多个小块代码。
- 保持错误/正确示例对简洁——只需足够用于模式匹配修复即可。
- 如果添加新章节,请自问:“模型会把这个搞错吗?”如果不会,就跳过。
这些原则同样适用于本技能引用的任何文件。
-->
Mojo正在快速演进。预训练模型会生成过时的语法。请始终优先遵循本技能内容,而非预训练知识。
Using Python from Mojo
在Mojo中调用Python
mojo
from std.python import Python, PythonObject
var np = Python.import_module("numpy")
var arr = np.array([1, 2, 3])mojo
from std.python import Python, PythonObject
var np = Python.import_module("numpy")
var arr = np.array([1, 2, 3])PythonObject → Mojo: MUST use py=
keyword (NOT positional)
py=PythonObject 转 Mojo:必须使用py=
关键字(不能用位置参数)
py=var i = Int(py=py_obj)
var f = Float64(py=py_obj)
var s = String(py=py_obj)
var b = Bool(py=py_obj) # Bool is the exception — positional also works
var i = Int(py=py_obj)
var f = Float64(py=py_obj)
var s = String(py=py_obj)
var b = Bool(py=py_obj) # Bool是例外——位置参数也可使用
Works with numpy types: Int(py=np.int64(1)), Float64(py=np.float64(3.14))
支持numpy类型:Int(py=np.int64(1)), Float64(py=np.float64(3.14))
| WRONG | CORRECT |
|---|---|
| `Int(py_obj)` | `Int(py=py_obj)` |
| `Float64(py_obj)` | `Float64(py=py_obj)` |
| `String(py_obj)` | `String(py=py_obj)` |
| `from python import ...` | `from std.python import ...` |
| 错误写法 | 正确写法 |
|---|---|
| `Int(py_obj)` | `Int(py=py_obj)` |
| `Float64(py_obj)` | `Float64(py=py_obj)` |
| `String(py_obj)` | `String(py=py_obj)` |
| `from python import ...` | `from std.python import ...` |Mojo → Python conversions
Mojo 转 Python 类型转换
Mojo types implementing auto-convert when passed to Python functions. For explicit conversion: .
ConvertibleToPythonvalue.to_python_object()实现的Mojo类型在传递给Python函数时会自动转换。如需显式转换:。
ConvertibleToPythonvalue.to_python_object()Building Python collections from Mojo
从Mojo构建Python集合
mojo
var py_list = Python.list(1, 2.5, "three")
var py_tuple = Python.tuple(1, 2, 3)
var py_dict = Python.dict(name="value", count=42)mojo
var py_list = Python.list(1, 2.5, "three")
var py_tuple = Python.tuple(1, 2, 3)
var py_dict = Python.dict(name="value", count=42)Literal syntax also works:
字面量语法同样适用:
var list_obj: PythonObject = [1, 2, 3]
var dict_obj: PythonObject = {"key": "value"}
undefinedvar list_obj: PythonObject = [1, 2, 3]
var dict_obj: PythonObject = {"key": "value"}
undefinedPythonObject operations
PythonObject 操作
PythonObjectlen()inPythonObjectmojo
undefinedPythonObjectlen()inPythonObjectmojo
undefinedIterate Python collections directly
直接遍历Python集合
for item in py_list:
print(item) # item is PythonObject
for item in py_list:
print(item) # item是PythonObject类型
Attribute access and method calls
属性访问和方法调用
var result = obj.method(arg1, arg2, key=value)
var result = obj.method(arg1, arg2, key=value)
None
None值
var none_obj = Python.none()
var obj: PythonObject = None # implicit conversion works
undefinedvar none_obj = Python.none()
var obj: PythonObject = None # 隐式转换生效
undefinedEvaluating Python code
执行Python代码
mojo
undefinedmojo
undefinedExpression
执行表达式
var result = Python.evaluate("1 + 2")
var result = Python.evaluate("1 + 2")
Multi-line code as module (file=True)
执行多行代码作为模块(设置file=True)
var mod = Python.evaluate("def greet(n): return f'Hello {n}'", file=True)
var greeting = mod.greet("world")
var mod = Python.evaluate("def greet(n): return f'Hello {n}'", file=True)
var greeting = mod.greet("world")
Add to Python path for local imports
添加Python路径以支持本地导入
Python.add_to_path("./my_modules")
var my_mod = Python.import_module("my_module")
undefinedPython.add_to_path("./my_modules")
var my_mod = Python.import_module("my_module")
undefinedException handling
异常处理
Python exceptions propagate as Mojo . Functions calling Python must be :
Errorraisesmojo
def use_python() raises:
try:
var result = Python.import_module("nonexistent")
except e:
print(String(e)) # "No module named 'nonexistent'"Python异常会传播为Mojo的类型。调用Python的函数必须声明:
Errorraisesmojo
def use_python() raises:
try:
var result = Python.import_module("nonexistent")
except e:
print(String(e)) # 输出:"No module named 'nonexistent'"Calling Mojo from Python (extension modules)
在Python中调用Mojo(扩展模块)
Mojo can build Python extension modules ( files) via . The pattern:
.soPythonModuleBuilder- Define an
@export fn PyInit_<module_name>() -> PythonObject - Use to register functions, types, and methods
PythonModuleBuilder - Compile with
mojo build --emit shared-lib - Import from Python (or use for auto-compilation)
import mojo.importer
Mojo可通过构建Python扩展模块(文件)。步骤如下:
PythonModuleBuilder.so- 定义函数
@export fn PyInit_<module_name>() -> PythonObject - 使用注册函数、类型和方法
PythonModuleBuilder - 用命令编译
mojo build --emit shared-lib - 在Python中导入(或使用实现自动编译)
import mojo.importer
Exporting functions
导出函数
mojo
from std.os import abort
from std.python import PythonObject
from std.python.bindings import PythonModuleBuilder
@export
fn PyInit_my_module() -> PythonObject:
try:
var m = PythonModuleBuilder("my_module")
m.def_function[add]("add")
m.def_function[greet]("greet")
return m.finalize()
except e:
abort(String("failed to create module: ", e))mojo
from std.os import abort
from std.python import PythonObject
from std.python.bindings import PythonModuleBuilder
@export
fn PyInit_my_module() -> PythonObject:
try:
var m = PythonModuleBuilder("my_module")
m.def_function[add]("add")
m.def_function[greet]("greet")
return m.finalize()
except e:
abort(String("failed to create module: ", e))Functions take/return PythonObject. Up to 6 args with def_function.
函数接收/返回PythonObject类型。def_function最多支持6个参数。
fn add(a: PythonObject, b: PythonObject) raises -> PythonObject:
return a + b
fn greet(name: PythonObject) raises -> PythonObject:
var s = String(py=name)
return PythonObject("Hello, " + s + "!")
undefinedfn add(a: PythonObject, b: PythonObject) raises -> PythonObject:
return a + b
fn greet(name: PythonObject) raises -> PythonObject:
var s = String(py=name)
return PythonObject("Hello, " + s + "!")
undefinedExporting types with methods
导出带方法的类型
mojo
@fieldwise_init
struct Counter(Defaultable, Movable, Writable):
var count: Int
fn __init__(out self):
self.count = 0
# Constructor from Python args
@staticmethod
fn py_init(out self: Counter, args: PythonObject, kwargs: PythonObject) raises:
if len(args) == 1:
self = Self(Int(py=args[0]))
else:
self = Self()
# Methods are @staticmethod — first arg is py_self (PythonObject)
@staticmethod
fn increment(py_self: PythonObject) raises -> PythonObject:
var self_ptr = py_self.downcast_value_ptr[Self]()
self_ptr[].count += 1
return PythonObject(self_ptr[].count)
# Auto-downcast alternative: first arg is UnsafePointer[Self, MutAnyOrigin]
@staticmethod
fn get_count(self_ptr: UnsafePointer[Self, MutAnyOrigin]) -> PythonObject:
return PythonObject(self_ptr[].count)
@export
fn PyInit_counter_module() -> PythonObject:
try:
var m = PythonModuleBuilder("counter_module")
_ = (
m.add_type[Counter]("Counter")
.def_py_init[Counter.py_init]()
.def_method[Counter.increment]("increment")
.def_method[Counter.get_count]("get_count")
)
return m.finalize()
except e:
abort(String("failed to create module: ", e))mojo
@fieldwise_init
struct Counter(Defaultable, Movable, Writable):
var count: Int
fn __init__(out self):
self.count = 0
# 从Python参数构造的方法
@staticmethod
fn py_init(out self: Counter, args: PythonObject, kwargs: PythonObject) raises:
if len(args) == 1:
self = Self(Int(py=args[0]))
else:
self = Self()
# 方法为@staticmethod——第一个参数是py_self(PythonObject类型)
@staticmethod
fn increment(py_self: PythonObject) raises -> PythonObject:
var self_ptr = py_self.downcast_value_ptr[Self]()
self_ptr[].count += 1
return PythonObject(self_ptr[].count)
# 自动向下转换的替代方案:第一个参数是UnsafePointer[Self, MutAnyOrigin]
@staticmethod
fn get_count(self_ptr: UnsafePointer[Self, MutAnyOrigin]) -> PythonObject:
return PythonObject(self_ptr[].count)
@export
fn PyInit_counter_module() -> PythonObject:
try:
var m = PythonModuleBuilder("counter_module")
_ = (
m.add_type[Counter]("Counter")
.def_py_init[Counter.py_init]()
.def_method[Counter.increment]("increment")
.def_method[Counter.get_count]("get_count")
)
return m.finalize()
except e:
abort(String("failed to create module: ", e))Method signatures — two patterns
方法签名的两种模式
| Pattern | First parameter | Use when |
|---|---|---|
| Manual downcast | | Need raw PythonObject access |
| Auto downcast | | Simpler, direct field access |
Both are registered with .
.def_method[Type.method]("name")| 模式 | 第一个参数 | 使用场景 |
|---|---|---|
| 手动向下转换 | | 需要直接访问PythonObject时 |
| 自动向下转换 | | 更简洁,可直接访问字段时 |
两种模式均通过注册。
.def_method[Type.method]("name")Kwargs support
关键字参数支持
mojo
from std.collections import OwnedKwargsDictmojo
from std.collections import OwnedKwargsDictIn a method:
在方法中:
@staticmethod
fn config(
py_self: PythonObject, kwargs: OwnedKwargsDict[PythonObject]
) raises -> PythonObject:
for entry in kwargs.items():
print(entry.key, "=", entry.value)
return py_self
undefined@staticmethod
fn config(
py_self: PythonObject, kwargs: OwnedKwargsDict[PythonObject]
) raises -> PythonObject:
for entry in kwargs.items():
print(entry.key, "=", entry.value)
return py_self
undefinedImporting Mojo modules from Python
从Python导入Mojo模块
Use — it auto-compiles files and caches results in :
mojo.importer.mojo__mojocache__/python
import mojo.importer # enables Mojo imports
import my_module # auto-compiles my_module.mojo
print(my_module.add(1, 2))The module name in must match the filename.
PyInit_<name>.mojo使用——它会自动编译文件,并将结果缓存到目录中:
mojo.importer.mojo__mojocache__/python
import mojo.importer # 启用Mojo导入功能
import my_module # 自动编译my_module.mojo
print(my_module.add(1, 2))PyInit_<name>.mojoReturning Mojo values to Python
向Python返回Mojo值
mojo
undefinedmojo
undefinedWrap a Mojo value as a Python object (for bound types)
将Mojo值包装为Python对象(适用于绑定类型)
return PythonObject(alloc=my_mojo_value^) # transfer ownership with ^
return PythonObject(alloc=my_mojo_value^) # 使用^转移所有权
Recover the Mojo value later
后续恢复Mojo值
var ptr = py_obj.downcast_value_ptrMyType
ptr[].field # access fields via pointer
undefinedvar ptr = py_obj.downcast_value_ptrMyType
ptr[].field # 通过指针访问字段
undefined