1 介绍

1.1 定义与概念

01.go-python3简介
    a.基本定义
        go-python3是Go语言调用CPython3的C API绑定库,允许在Go程序中直接执行Python代码和调用Python函数。
    b.项目来源
        由DataDog公司开源维护,GitHub地址:github.com/DataDog/go-python3。

02.核心概念
    a.CGO桥接
        通过CGO技术实现Go与CPython C API的互操作。
    b.CPython C API
        CPython提供的C语言接口,用于嵌入Python解释器或扩展Python功能。
    c.引用计数
        Python对象使用引用计数进行内存管理,需要手动调用IncRef和DecRef。

03.应用场景
    a.代码复用
        复用现有的Python库和算法,避免重复造轮子。
    b.性能互补
        Go负责高性能并发,Python负责科学计算和机器学习。
    c.快速原型
        利用Python的快速开发特性进行算法验证。

1.2 核心特性

01.直接调用CPython API
    a.原生绑定
        直接映射CPython的C API函数,保持API的一致性。
    b.完整功能
        支持对象操作、模块导入、异常处理等全部CPython功能。
    c.示例代码
        a.功能说明
            展示基本的CPython API调用流程。
        b.代码示例
            ---
            package main

            import (
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                // 初始化Python解释器
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 执行Python代码
                python3.PyRun_SimpleString("print('Hello from Python!')")

                // 计算表达式
                result := python3.PyRun_SimpleString("result = 2 + 3")
                if result != 0 {
                    panic("Python执行失败")
                }
            }
            ---

02.类型系统映射
    a.基本类型
        支持int、float、string、bool等基本类型的双向转换。
    b.复杂类型
        支持list、dict、tuple等复杂数据结构。
    c.自定义对象
        可以操作Python自定义类和对象。

03.内存管理
    a.引用计数机制
        所有PyObject需要手动管理引用计数。
    b.IncRef与DecRef
        IncRef增加引用,DecRef减少引用,引用为0时自动释放。
    c.内存安全
        正确使用引用计数可避免内存泄漏和悬空指针。

1.3 优缺点分析

01.主要优势
    a.性能优势
        直接调用C API,性能接近原生CPython。
    b.库生态
        可以使用Python丰富的第三方库生态(NumPy、Pandas、TensorFlow等)。
    c.开发效率
        Go负责系统编程,Python负责数据处理,各取所长。
    d.零序列化
        数据在内存中直接传递,无需JSON/Protocol Buffers等序列化。

02.主要限制
    a.CGO开销
        CGO调用存在性能开销,频繁调用会影响性能。
    b.GIL限制
        受Python全局解释器锁(GIL)限制,无法实现真正的并行计算。
    c.内存管理复杂
        需要手动管理Python对象引用计数,容易出错。
    d.调试困难
        跨语言调试比单语言调试更复杂。

03.适用场景
    a.适合使用
        需要调用特定Python库、算法验证、数据科学任务。
    b.不适合使用
        对性能要求极高的场景、需要高并发的计算密集型任务。

1.4 使用场景

01.机器学习集成
    a.模型训练
        使用Python训练模型,Go进行推理服务。
    b.数据预处理
        利用Pandas进行数据清洗和特征工程。
    c.代码示例
        a.功能说明
            在Go中调用sklearn训练模型。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 训练简单模型
                python3.PyRun_SimpleString(`
                from sklearn.linear_model import LinearRegression
                import numpy as np

                X = np.array([[1], [2], [3], [4], [5]])
                y = np.array([2, 4, 6, 8, 10])

                model = LinearRegression()
                model.fit(X, y)

                print(f"Coefficient: {model.coef_[0]}")
                print(f"Intercept: {model.intercept_}")
                `)
            }
            ---

02.科学计算
    a.数值计算
        使用NumPy进行高性能数值计算。
    b.数据可视化
        调用matplotlib生成图表。
    c.信号处理
        使用SciPy进行信号处理和分析。

03.脚本自动化
    a.任务调度
        Go编写调度器,Python执行具体任务。
    b.数据采集
        利用Python丰富的爬虫库进行数据采集。
    c.文本处理
        使用Python的正则表达式和NLP库处理文本。

1.5 架构设计

01.系统架构
    a.分层结构
        Go应用层 → go-python3绑定层 → CPython C API → Python解释器。
    b.调用流程
        Go函数 → CGO调用 → C API → Python代码执行 → 结果返回。

02.内存模型
    a.Go内存
        Go对象由Go GC管理。
    b.Python内存
        Python对象由引用计数和GC管理。
    c.边界管理
        跨语言传递时需要显式转换和引用计数管理。

03.并发模型
    a.Go协程
        使用goroutine实现并发。
    b.GIL约束
        同一时刻只有一个线程执行Python代码。
    c.并发策略
        a.功能说明
            通过多进程或异步IO绕过GIL限制。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                "runtime"
                "sync"
                python3 "github.com/DataDog/go-python3"
            )

            func worker(id int, wg *sync.WaitGroup) {
                defer wg.Done()
                runtime.LockOSThread()
                defer runtime.UnlockOSThread()

                gilState := python3.PyGILState_Ensure()
                defer python3.PyGILState_Release(gilState)

                code := fmt.Sprintf(`print("Worker %d executing")`, id)
                python3.PyRun_SimpleString(code)
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                var wg sync.WaitGroup
                for i := 0; i < 5; i++ {
                    wg.Add(1)
                    go worker(i, &wg)
                }
                wg.Wait()
            }
            ---

1.6 与CPython集成

01.嵌入式Python
    a.解释器嵌入
        将Python解释器嵌入到Go应用中。
    b.生命周期
        Py_Initialize初始化,Py_Finalize终止。
    c.初始化示例
        a.功能说明
            正确初始化和终止Python解释器。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                // 检查是否已初始化
                if !python3.Py_IsInitialized() {
                    python3.Py_Initialize()
                }

                // 获取Python版本
                version := python3.Py_GetVersion()
                fmt.Printf("Python版本: %s\n", version)

                // 执行代码
                python3.PyRun_SimpleString("import sys")
                python3.PyRun_SimpleString("print(sys.version)")

                // 终止解释器
                python3.Py_Finalize()
            }
            ---

02.模块系统
    a.标准库
        可以导入所有Python标准库模块。
    b.第三方库
        支持pip安装的第三方库。
    c.导入示例
        a.功能说明
            导入并使用Python模块。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 导入json模块
                jsonModule := python3.PyImport_ImportModule("json")
                if jsonModule == nil {
                    python3.PyErr_Print()
                    return
                }
                defer jsonModule.DecRef()

                // 获取dumps函数
                dumps := python3.PyObject_GetAttrString(jsonModule, "dumps")
                if dumps == nil {
                    python3.PyErr_Print()
                    return
                }
                defer dumps.DecRef()

                // 创建Python字典
                dict := python3.PyDict_New()
                defer dict.DecRef()
                python3.PyDict_SetItemString(dict, "key", python3.PyUnicode_FromString("value"))

                // 调用dumps
                args := python3.PyTuple_New(1)
                defer args.DecRef()
                python3.PyTuple_SetItem(args, 0, dict)
                dict.IncRef()

                result := dumps.CallObject(args)
                defer result.DecRef()

                jsonStr := python3.PyUnicode_AsUTF8(result)
                fmt.Printf("JSON: %s\n", jsonStr)
            }
            ---

03.C API映射
    a.函数映射
        每个CPython C API函数都有对应的Go函数。
    b.类型映射
        PyObject、PyTypeObject等类型映射为Go类型。

1.7 GIL机制

01.GIL概念
    a.全局解释器锁
        CPython使用GIL确保同一时刻只有一个线程执行Python字节码。
    b.锁的作用
        保护Python解释器内部数据结构的线程安全。
    c.性能影响
        限制了多线程Python程序的并行执行能力。

02.GIL管理API
    a.PyGILState_Ensure
        在Go线程中获取GIL,确保可以安全调用Python API。
    b.PyGILState_Release
        释放GIL,允许其他线程执行Python代码。
    c.使用示例
        a.功能说明
            在多线程环境中正确管理GIL。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                "runtime"
                "sync"
                python3 "github.com/DataDog/go-python3"
            )

            func pythonTask(taskID int, wg *sync.WaitGroup) {
                defer wg.Done()

                // 锁定OS线程
                runtime.LockOSThread()
                defer runtime.UnlockOSThread()

                // 获取GIL
                gilState := python3.PyGILState_Ensure()
                defer python3.PyGILState_Release(gilState)

                // 执行Python代码
                code := fmt.Sprintf(`
                import time
                start = time.time()
                sum([i**2 for i in range(1000)])
                elapsed = time.time() - start
                print(f"Task {%d} completed in {{elapsed:.4f}}s")
                `, taskID)

                python3.PyRun_SimpleString(code)
            }

            func main() {
                // 初始化解释器
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                var wg sync.WaitGroup
                numTasks := 4

                for i := 0; i < numTasks; i++ {
                    wg.Add(1)
                    go pythonTask(i, &wg)
                }

                wg.Wait()
                fmt.Println("所有任务完成")
            }
            ---

03.性能优化
    a.减少GIL竞争
        尽量减少频繁获取和释放GIL的操作。
    b.批量处理
        将多个小任务合并成一个大任务,减少GIL切换。
    c.使用子解释器
        每个子解释器有独立的状态,但仍共享GIL。

2 基础使用

2.1 初始化与终止

01.Py_Initialize
    a.功能说明
        初始化Python解释器,必须在调用其他Python API之前执行。
    b.初始化示例
        a.功能说明
            基本的解释器初始化和终止流程。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                // 初始化Python解释器
                python3.Py_Initialize()

                // 检查是否成功初始化
                if python3.Py_IsInitialized() {
                    fmt.Println("Python解释器初始化成功")
                }

                // 执行简单的Python代码
                python3.PyRun_SimpleString("print('Hello from Python')")

                // 终止Python解释器
                python3.Py_Finalize()
            }
            ---

02.Py_Finalize
    a.功能说明
        终止Python解释器,释放所有资源。
    b.注意事项
        Finalize后不能再调用Python API,除非重新Initialize。
    c.使用defer
        建议使用defer确保解释器正确终止。

03.Py_IsInitialized
    a.功能说明
        检查Python解释器是否已初始化。
    b.检查示例
        a.功能说明
            避免重复初始化解释器。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func ensureInitialized() {
                if !python3.Py_IsInitialized() {
                    python3.Py_Initialize()
                    fmt.Println("解释器已初始化")
                } else {
                    fmt.Println("解释器已经初始化过了")
                }
            }

            func main() {
                ensureInitialized()
                ensureInitialized() // 第二次调用不会重复初始化

                defer python3.Py_Finalize()
                python3.PyRun_SimpleString("print('Running Python code')")
            }
            ---

04.初始化配置
    a.Py_SetProgramName
        设置Python程序名称。
    b.Py_SetPythonHome
        设置Python的HOME目录。

2.2 执行Python代码

01.PyRun_SimpleString
    a.功能说明
        执行简单的Python字符串代码。
    b.返回值
        成功返回0,失败返回-1。
    c.执行示例
        a.功能说明
            执行Python代码并处理返回值。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 执行简单语句
                ret := python3.PyRun_SimpleString("x = 100")
                if ret != 0 {
                    fmt.Println("执行失败")
                    return
                }

                // 执行计算
                python3.PyRun_SimpleString("y = x * 2")

                // 打印结果
                python3.PyRun_SimpleString("print(f'x={x}, y={y}')")

                // 执行复杂代码块
                code := `
                def fibonacci(n):
                    if n <= 1:
                        return n
                    return fibonacci(n-1) + fibonacci(n-2)

                for i in range(10):
                    print(f"fib({i}) = {fibonacci(i)}")
                `
                python3.PyRun_SimpleString(code)
            }
            ---

02.PyRun_SimpleFile
    a.功能说明
        从文件执行Python代码。
    b.文件参数
        需要传入*FILE指针和文件名。

03.执行表达式
    a.计算表达式
        使用PyRun_String计算表达式并返回结果。
    b.表达式示例
        a.功能说明
            计算Python表达式并获取结果。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 获取__main__模块
                mainModule := python3.PyImport_AddModule("__main__")
                mainDict := python3.PyModule_GetDict(mainModule)

                // 计算表达式
                expr := "2 ** 10 + 5 * 3"
                result := python3.PyRun_String(expr, python3.Py_eval_input, mainDict, mainDict)
                if result == nil {
                    python3.PyErr_Print()
                    return
                }
                defer result.DecRef()

                // 转换为Go类型
                value := python3.PyLong_AsLong(result)
                fmt.Printf("表达式 '%s' 的结果: %d\n", expr, value)
            }
            ---

2.3 调用Python函数

01.获取函数对象
    a.PyObject_GetAttrString
        从模块或对象获取属性(包括函数)。
    b.函数调用流程
        获取模块 → 获取函数 → 构造参数 → 调用函数 → 处理返回值。

02.构造参数
    a.PyTuple_New
        创建参数元组,Python函数参数以tuple形式传递。
    b.PyTuple_SetItem
        设置元组中的参数值。
    c.参数示例
        a.功能说明
            构造并传递多个参数给Python函数。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 定义Python函数
                python3.PyRun_SimpleString(`
                def add(a, b):
                    return a + b

                def greet(name, age):
                    return f"Hello {name}, you are {age} years old"
                `)

                mainModule := python3.PyImport_AddModule("__main__")

                // 调用add函数
                addFunc := python3.PyObject_GetAttrString(mainModule, "add")
                defer addFunc.DecRef()

                args := python3.PyTuple_New(2)
                defer args.DecRef()
                python3.PyTuple_SetItem(args, 0, python3.PyLong_FromGoInt(10))
                python3.PyTuple_SetItem(args, 1, python3.PyLong_FromGoInt(20))

                result := addFunc.CallObject(args)
                defer result.DecRef()
                fmt.Printf("add(10, 20) = %d\n", python3.PyLong_AsLong(result))

                // 调用greet函数
                greetFunc := python3.PyObject_GetAttrString(mainModule, "greet")
                defer greetFunc.DecRef()

                greetArgs := python3.PyTuple_New(2)
                defer greetArgs.DecRef()
                python3.PyTuple_SetItem(greetArgs, 0, python3.PyUnicode_FromString("Alice"))
                python3.PyTuple_SetItem(greetArgs, 1, python3.PyLong_FromGoInt(25))

                greetResult := greetFunc.CallObject(greetArgs)
                defer greetResult.DecRef()
                fmt.Println(python3.PyUnicode_AsUTF8(greetResult))
            }
            ---

03.调用方式
    a.CallObject
        使用位置参数调用函数。
    b.Call
        同时支持位置参数和关键字参数。
    c.CallMethod
        直接调用对象的方法。

2.4 导入模块

01.PyImport_ImportModule
    a.功能说明
        导入Python模块,返回模块对象。
    b.模块名称
        使用Python模块的完整名称(如"os.path")。
    c.导入示例
        a.功能说明
            导入标准库模块并调用其函数。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 导入math模块
                mathModule := python3.PyImport_ImportModule("math")
                if mathModule == nil {
                    python3.PyErr_Print()
                    return
                }
                defer mathModule.DecRef()

                // 获取sqrt函数
                sqrtFunc := python3.PyObject_GetAttrString(mathModule, "sqrt")
                if sqrtFunc == nil {
                    python3.PyErr_Print()
                    return
                }
                defer sqrtFunc.DecRef()

                // 调用sqrt(16)
                args := python3.PyTuple_New(1)
                defer args.DecRef()
                python3.PyTuple_SetItem(args, 0, python3.PyFloat_FromDouble(16.0))

                result := sqrtFunc.CallObject(args)
                defer result.DecRef()

                value := python3.PyFloat_AsDouble(result)
                fmt.Printf("sqrt(16) = %.2f\n", value)

                // 获取常量pi
                pi := python3.PyObject_GetAttrString(mathModule, "pi")
                defer pi.DecRef()
                fmt.Printf("pi = %.6f\n", python3.PyFloat_AsDouble(pi))
            }
            ---

02.PyImport_AddModule
    a.功能说明
        获取已导入的模块,如__main__。
    b.__main__模块
        主模块,PyRun_SimpleString执行的代码都在此模块中。

03.导入自定义模块
    a.sys.path
        Python模块搜索路径。
    b.添加路径
        通过修改sys.path添加自定义模块路径。
    c.自定义模块示例
        a.功能说明
            导入自定义路径的Python模块。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 添加模块搜索路径
                python3.PyRun_SimpleString(`
                import sys
                sys.path.insert(0, '/path/to/modules')
                `)

                // 导入自定义模块
                customModule := python3.PyImport_ImportModule("mymodule")
                if customModule == nil {
                    fmt.Println("导入失败")
                    python3.PyErr_Print()
                    return
                }
                defer customModule.DecRef()

                fmt.Println("自定义模块导入成功")
            }
            ---

2.5 类型转换

01.整数转换
    a.PyLong_FromGoInt
        将Go int转换为Python int对象。
    b.PyLong_AsLong
        将Python int转换为Go int。
    c.整数示例
        a.功能说明
            Go和Python整数的双向转换。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // Go → Python
                goInt := 42
                pyInt := python3.PyLong_FromGoInt(goInt)
                defer pyInt.DecRef()

                // Python → Go
                backToGo := python3.PyLong_AsLong(pyInt)
                fmt.Printf("原始值: %d, 转换后: %d\n", goInt, backToGo)

                // 处理大整数
                python3.PyRun_SimpleString("big_num = 2 ** 100")
                mainModule := python3.PyImport_AddModule("__main__")
                bigNum := python3.PyObject_GetAttrString(mainModule, "big_num")
                defer bigNum.DecRef()

                // PyLong_AsLong对于大整数会溢出,使用字符串转换
                bigNumStr := python3.PyObject_Str(bigNum)
                defer bigNumStr.DecRef()
                fmt.Printf("大整数: %s\n", python3.PyUnicode_AsUTF8(bigNumStr))
            }
            ---

02.浮点数转换
    a.PyFloat_FromDouble
        将Go float64转换为Python float。
    b.PyFloat_AsDouble
        将Python float转换为Go float64。

03.字符串转换
    a.PyUnicode_FromString
        将Go string转换为Python str。
    b.PyUnicode_AsUTF8
        将Python str转换为Go string。
    c.字符串示例
        a.功能说明
            Go和Python字符串的双向转换。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // Go → Python
                goStr := "Hello, 世界"
                pyStr := python3.PyUnicode_FromString(goStr)
                defer pyStr.DecRef()

                // Python处理
                python3.PyRun_SimpleString("result = None")
                mainModule := python3.PyImport_AddModule("__main__")
                mainDict := python3.PyModule_GetDict(mainModule)

                python3.PyDict_SetItemString(mainDict, "input_str", pyStr)
                python3.PyRun_SimpleString("result = input_str.upper()")

                // Python → Go
                result := python3.PyObject_GetAttrString(mainModule, "result")
                defer result.DecRef()

                backToGo := python3.PyUnicode_AsUTF8(result)
                fmt.Printf("原始: %s\n转换: %s\n", goStr, backToGo)
            }
            ---

04.布尔值转换
    a.Py_True和Py_False
        Python的True和False单例对象。
    b.PyBool_FromLong
        从整数创建布尔值(0为False,非0为True)。

2.6 返回值处理

01.检查返回值
    a.NULL检查
        Python API调用失败时返回NULL。
    b.错误处理
        返回NULL时应该使用PyErr_Print打印错误。
    c.检查示例
        a.功能说明
            正确处理Python函数调用的返回值和错误。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func safeDivide(a, b int) (float64, error) {
                python3.PyRun_SimpleString(`
                def divide(x, y):
                    return x / y
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                divideFunc := python3.PyObject_GetAttrString(mainModule, "divide")
                if divideFunc == nil {
                    return 0, fmt.Errorf("获取函数失败")
                }
                defer divideFunc.DecRef()

                args := python3.PyTuple_New(2)
                defer args.DecRef()
                python3.PyTuple_SetItem(args, 0, python3.PyLong_FromGoInt(a))
                python3.PyTuple_SetItem(args, 1, python3.PyLong_FromGoInt(b))

                result := divideFunc.CallObject(args)
                if result == nil {
                    python3.PyErr_Print()
                    return 0, fmt.Errorf("除法调用失败")
                }
                defer result.DecRef()

                return python3.PyFloat_AsDouble(result), nil
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 正常调用
                if result, err := safeDivide(10, 2); err == nil {
                    fmt.Printf("10 / 2 = %.2f\n", result)
                } else {
                    fmt.Printf("错误: %v\n", err)
                }

                // 除零错误
                if result, err := safeDivide(10, 0); err == nil {
                    fmt.Printf("10 / 0 = %.2f\n", result)
                } else {
                    fmt.Printf("错误: %v\n", err)
                }
            }
            ---

02.引用计数管理
    a.DecRef规则
        所有返回的PyObject都需要DecRef。
    b.IncRef时机
        当需要延长对象生命周期时调用IncRef。
    c.引用管理示例
        a.功能说明
            正确管理Python对象的引用计数。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 创建对象
                pyInt := python3.PyLong_FromGoInt(100)
                fmt.Printf("创建对象,引用计数: %d\n", pyInt.RefCnt())

                // 增加引用
                pyInt.IncRef()
                fmt.Printf("IncRef后,引用计数: %d\n", pyInt.RefCnt())

                // 减少引用
                pyInt.DecRef()
                fmt.Printf("第一次DecRef后,引用计数: %d\n", pyInt.RefCnt())

                // 最终释放
                pyInt.DecRef()
                fmt.Println("对象已释放")
            }
            ---

03.类型检查
    a.PyLong_Check
        检查对象是否为整数类型。
    b.PyFloat_Check
        检查对象是否为浮点数类型。
    c.PyUnicode_Check
        检查对象是否为字符串类型。

3 数据交互

3.1 基本类型转换

01.整数类型
    a.Go int到Python int
        使用PyLong_FromGoInt和PyLong_FromLong。
    b.Python int到Go int
        使用PyLong_AsLong和PyLong_AsLongLong。
    c.整数转换示例
        a.功能说明
            演示各种整数类型的转换。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // int8到Python
                var i8 int8 = 127
                pyInt8 := python3.PyLong_FromLong(int(i8))
                defer pyInt8.DecRef()

                // int32到Python
                var i32 int32 = 2147483647
                pyInt32 := python3.PyLong_FromLong(int(i32))
                defer pyInt32.DecRef()

                // int64到Python
                var i64 int64 = 9223372036854775807
                pyInt64 := python3.PyLong_FromLongLong(i64)
                defer pyInt64.DecRef()

                // Python到Go
                python3.PyRun_SimpleString("x = 12345")
                mainModule := python3.PyImport_AddModule("__main__")
                pyX := python3.PyObject_GetAttrString(mainModule, "x")
                defer pyX.DecRef()

                goX := python3.PyLong_AsLong(pyX)
                fmt.Printf("Python x = %d\n", goX)
            }
            ---

02.浮点类型
    a.Go float到Python float
        使用PyFloat_FromDouble。
    b.Python float到Go float
        使用PyFloat_AsDouble。
    c.浮点转换示例
        a.功能说明
            浮点数的双向转换和精度处理。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                "math"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // Go → Python
                goFloat := 3.141592653589793
                pyFloat := python3.PyFloat_FromDouble(goFloat)
                defer pyFloat.DecRef()

                // 在Python中计算
                mainModule := python3.PyImport_AddModule("__main__")
                mainDict := python3.PyModule_GetDict(mainModule)
                python3.PyDict_SetItemString(mainDict, "pi", pyFloat)

                python3.PyRun_SimpleString("result = pi * 2")

                // Python → Go
                pyResult := python3.PyObject_GetAttrString(mainModule, "result")
                defer pyResult.DecRef()

                goResult := python3.PyFloat_AsDouble(pyResult)
                fmt.Printf("2π = %.15f\n", goResult)

                // 特殊值处理
                pyInf := python3.PyFloat_FromDouble(math.Inf(1))
                defer pyInf.DecRef()
                fmt.Printf("Infinity: %v\n", math.IsInf(python3.PyFloat_AsDouble(pyInf), 1))
            }
            ---

03.布尔类型
    a.Py_True和Py_False
        Python的布尔单例对象。
    b.布尔检查
        使用PyObject_IsTrue判断对象真值。

3.2 复杂类型转换

01.列表类型
    a.PyList_New
        创建指定大小的Python列表。
    b.PyList_SetItem
        设置列表元素(不增加引用计数)。
    c.PyList_GetItem
        获取列表元素(返回借用引用)。
    d.列表示例
        a.功能说明
            创建和操作Python列表。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 创建列表
                pyList := python3.PyList_New(5)
                defer pyList.DecRef()

                // 填充数据
                for i := 0; i < 5; i++ {
                    python3.PyList_SetItem(pyList, i, python3.PyLong_FromGoInt(i*10))
                }

                // 获取列表大小
                size := python3.PyList_Size(pyList)
                fmt.Printf("列表大小: %d\n", size)

                // 读取元素
                fmt.Print("列表内容: [")
                for i := 0; i < size; i++ {
                    item := python3.PyList_GetItem(pyList, i)
                    if i > 0 {
                        fmt.Print(", ")
                    }
                    fmt.Print(python3.PyLong_AsLong(item))
                }
                fmt.Println("]")

                // 追加元素
                python3.PyList_Append(pyList, python3.PyLong_FromGoInt(50))
                fmt.Printf("追加后大小: %d\n", python3.PyList_Size(pyList))
            }
            ---

02.字典类型
    a.PyDict_New
        创建空字典。
    b.PyDict_SetItemString
        设置字典键值对(键为字符串)。
    c.PyDict_GetItemString
        获取字典值(返回借用引用)。
    d.字典示例
        a.功能说明
            创建和操作Python字典。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 创建字典
                pyDict := python3.PyDict_New()
                defer pyDict.DecRef()

                // 添加键值对
                python3.PyDict_SetItemString(pyDict, "name", python3.PyUnicode_FromString("Alice"))
                python3.PyDict_SetItemString(pyDict, "age", python3.PyLong_FromGoInt(30))
                python3.PyDict_SetItemString(pyDict, "score", python3.PyFloat_FromDouble(95.5))

                // 读取值
                name := python3.PyDict_GetItemString(pyDict, "name")
                age := python3.PyDict_GetItemString(pyDict, "age")
                score := python3.PyDict_GetItemString(pyDict, "score")

                fmt.Printf("Name: %s\n", python3.PyUnicode_AsUTF8(name))
                fmt.Printf("Age: %d\n", python3.PyLong_AsLong(age))
                fmt.Printf("Score: %.1f\n", python3.PyFloat_AsDouble(score))

                // 遍历字典
                keys := python3.PyDict_Keys(pyDict)
                defer keys.DecRef()

                size := python3.PyList_Size(keys)
                fmt.Println("\n字典所有键:")
                for i := 0; i < size; i++ {
                    key := python3.PyList_GetItem(keys, i)
                    fmt.Printf("  %s\n", python3.PyUnicode_AsUTF8(key))
                }
            }
            ---

03.元组类型
    a.PyTuple_New
        创建指定大小的元组。
    b.不可变性
        元组创建后不能修改大小。

3.3 Go到Python

01.切片转列表
    a.遍历切片
        遍历Go切片,逐个添加到Python列表。
    b.切片示例
        a.功能说明
            将Go切片转换为Python列表。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func goSliceToPyList(slice []int) *python3.PyObject {
                pyList := python3.PyList_New(len(slice))
                for i, v := range slice {
                    python3.PyList_SetItem(pyList, i, python3.PyLong_FromGoInt(v))
                }
                return pyList
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                goSlice := []int{10, 20, 30, 40, 50}
                pyList := goSliceToPyList(goSlice)
                defer pyList.DecRef()

                // 在Python中处理
                python3.PyRun_SimpleString(`
                def sum_list(lst):
                    return sum(lst)

                def avg_list(lst):
                    return sum(lst) / len(lst) if lst else 0
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                sumFunc := python3.PyObject_GetAttrString(mainModule, "sum_list")
                defer sumFunc.DecRef()

                args := python3.PyTuple_New(1)
                python3.PyTuple_SetItem(args, 0, pyList)
                pyList.IncRef()

                result := sumFunc.CallObject(args)
                defer result.DecRef()
                defer args.DecRef()

                fmt.Printf("Go切片: %v\n", goSlice)
                fmt.Printf("Python计算总和: %d\n", python3.PyLong_AsLong(result))
            }
            ---

02.map转字典
    a.遍历map
        遍历Go map,添加键值对到Python字典。
    b.map示例
        a.功能说明
            将Go map转换为Python字典。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func goMapToPyDict(m map[string]interface{}) *python3.PyObject {
                pyDict := python3.PyDict_New()
                for k, v := range m {
                    var pyValue *python3.PyObject
                    switch val := v.(type) {
                    case int:
                        pyValue = python3.PyLong_FromGoInt(val)
                    case float64:
                        pyValue = python3.PyFloat_FromDouble(val)
                    case string:
                        pyValue = python3.PyUnicode_FromString(val)
                    default:
                        continue
                    }
                    python3.PyDict_SetItemString(pyDict, k, pyValue)
                }
                return pyDict
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                goMap := map[string]interface{}{
                    "name":  "Bob",
                    "age":   25,
                    "score": 88.5,
                }

                pyDict := goMapToPyDict(goMap)
                defer pyDict.DecRef()

                // 在Python中使用
                mainModule := python3.PyImport_AddModule("__main__")
                mainDict := python3.PyModule_GetDict(mainModule)
                python3.PyDict_SetItemString(mainDict, "data", pyDict)

                python3.PyRun_SimpleString(`
                print(f"姓名: {data['name']}")
                print(f"年龄: {data['age']}")
                print(f"分数: {data['score']}")
                `)
            }
            ---

03.struct转字典
    a.反射遍历
        使用反射遍历struct字段。
    b.标签支持
        支持struct tag自定义字段名。

3.4 Python到Go

01.列表转切片
    a.获取列表大小
        使用PyList_Size获取元素个数。
    b.遍历转换
        遍历Python列表,转换每个元素到Go类型。
    c.列表转切片示例
        a.功能说明
            将Python列表转换为Go切片。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func pyListToGoSlice(pyList *python3.PyObject) []int {
                size := python3.PyList_Size(pyList)
                slice := make([]int, size)
                for i := 0; i < size; i++ {
                    item := python3.PyList_GetItem(pyList, i)
                    slice[i] = python3.PyLong_AsLong(item)
                }
                return slice
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 在Python中创建列表
                python3.PyRun_SimpleString(`
                result_list = [x**2 for x in range(10)]
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                pyList := python3.PyObject_GetAttrString(mainModule, "result_list")
                defer pyList.DecRef()

                // 转换为Go切片
                goSlice := pyListToGoSlice(pyList)
                fmt.Printf("Go切片: %v\n", goSlice)
                fmt.Printf("长度: %d\n", len(goSlice))
            }
            ---

02.字典转map
    a.获取键列表
        使用PyDict_Keys获取所有键。
    b.遍历转换
        遍历键,获取对应值并转换。
    c.字典转map示例
        a.功能说明
            将Python字典转换为Go map。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func pyDictToGoMap(pyDict *python3.PyObject) map[string]interface{} {
                goMap := make(map[string]interface{})
                keys := python3.PyDict_Keys(pyDict)
                defer keys.DecRef()

                size := python3.PyList_Size(keys)
                for i := 0; i < size; i++ {
                    key := python3.PyList_GetItem(keys, i)
                    keyStr := python3.PyUnicode_AsUTF8(key)

                    value := python3.PyDict_GetItem(pyDict, key)

                    if python3.PyLong_Check(value) {
                        goMap[keyStr] = python3.PyLong_AsLong(value)
                    } else if python3.PyFloat_Check(value) {
                        goMap[keyStr] = python3.PyFloat_AsDouble(value)
                    } else if python3.PyUnicode_Check(value) {
                        goMap[keyStr] = python3.PyUnicode_AsUTF8(value)
                    }
                }
                return goMap
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // Python创建字典
                python3.PyRun_SimpleString(`
                person = {
                    'name': 'Charlie',
                    'age': 35,
                    'height': 175.5
                }
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                pyDict := python3.PyObject_GetAttrString(mainModule, "person")
                defer pyDict.DecRef()

                // 转换为Go map
                goMap := pyDictToGoMap(pyDict)
                fmt.Printf("Go map: %+v\n", goMap)
            }
            ---

03.元组转数组
    a.固定大小
        元组大小固定,适合转换为数组。
    b.PyTuple_GetItem
        获取元组指定位置的元素。

3.5 内存管理

01.所有权规则
    a.新建引用
        PyXXX_New等创建函数返回新引用,需要DecRef。
    b.借用引用
        PyList_GetItem、PyDict_GetItem等返回借用引用,不需要DecRef。
    c.所有权示例
        a.功能说明
            演示新引用和借用引用的区别。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 新引用 - 需要DecRef
                pyInt := python3.PyLong_FromGoInt(42)
                fmt.Printf("新引用,初始计数: %d\n", pyInt.RefCnt())
                pyInt.DecRef()

                // 借用引用 - 不需要DecRef
                pyList := python3.PyList_New(3)
                defer pyList.DecRef()

                python3.PyList_SetItem(pyList, 0, python3.PyLong_FromGoInt(1))
                python3.PyList_SetItem(pyList, 1, python3.PyLong_FromGoInt(2))
                python3.PyList_SetItem(pyList, 2, python3.PyLong_FromGoInt(3))

                // GetItem返回借用引用
                item := python3.PyList_GetItem(pyList, 0)
                fmt.Printf("借用引用: %d\n", python3.PyLong_AsLong(item))
                // 不需要item.DecRef()

                // 如果需要保留借用引用,需要IncRef
                item.IncRef()
                fmt.Printf("IncRef后计数: %d\n", item.RefCnt())
                item.DecRef()
            }
            ---

02.循环引用
    a.GC处理
        Python GC可以处理循环引用。
    b.手动打破
        在Go侧及时DecRef避免循环引用。

03.内存泄漏检测
    a.引用计数追踪
        记录所有IncRef和DecRef调用。
    b.检测示例
        a.功能说明
            使用Python gc模块检测内存泄漏。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                import gc
                import sys

                def get_object_count():
                    gc.collect()
                    return len(gc.get_objects())

                initial_count = get_object_count()
                print(f"初始对象数: {initial_count}")
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                getCount := python3.PyObject_GetAttrString(mainModule, "get_object_count")
                defer getCount.DecRef()

                emptyArgs := python3.PyTuple_New(0)
                defer emptyArgs.DecRef()

                // 创建一些对象
                for i := 0; i < 100; i++ {
                    obj := python3.PyLong_FromGoInt(i)
                    obj.DecRef()
                }

                // 检查对象数量
                count := getCount.CallObject(emptyArgs)
                defer count.DecRef()

                finalCount := python3.PyLong_AsLong(count)
                fmt.Printf("最终对象数: %d\n", finalCount)
            }
            ---

3.6 引用计数

01.IncRef和DecRef
    a.IncRef
        增加对象引用计数,延长对象生命周期。
    b.DecRef
        减少对象引用计数,计数为0时释放对象。
    c.引用示例
        a.功能说明
            正确使用IncRef和DecRef管理对象。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 创建对象
                obj := python3.PyUnicode_FromString("Hello")
                fmt.Printf("创建后引用计数: %d\n", obj.RefCnt())

                // 增加引用
                obj.IncRef()
                fmt.Printf("IncRef后引用计数: %d\n", obj.RefCnt())

                obj.IncRef()
                fmt.Printf("再次IncRef后引用计数: %d\n", obj.RefCnt())

                // 减少引用
                obj.DecRef()
                fmt.Printf("第一次DecRef后引用计数: %d\n", obj.RefCnt())

                obj.DecRef()
                fmt.Printf("第二次DecRef后引用计数: %d\n", obj.RefCnt())

                obj.DecRef()
                fmt.Println("对象已释放")
            }
            ---

02.SetItem特殊情况
    a.PyList_SetItem
        会窃取引用,不需要对设置的对象DecRef。
    b.PyDict_SetItem
        不窃取引用,需要对设置的对象DecRef。
    c.SetItem示例
        a.功能说明
            演示SetItem的引用计数行为。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // PyList_SetItem窃取引用
                pyList := python3.PyList_New(2)
                defer pyList.DecRef()

                item1 := python3.PyLong_FromGoInt(100)
                fmt.Printf("item1引用计数: %d\n", item1.RefCnt())
                python3.PyList_SetItem(pyList, 0, item1)
                // 不需要item1.DecRef(),SetItem已窃取引用

                // PyDict_SetItem不窃取引用
                pyDict := python3.PyDict_New()
                defer pyDict.DecRef()

                key := python3.PyUnicode_FromString("key")
                value := python3.PyLong_FromGoInt(200)
                fmt.Printf("value引用计数: %d\n", value.RefCnt())

                python3.PyDict_SetItem(pyDict, key, value)
                fmt.Printf("SetItem后value引用计数: %d\n", value.RefCnt())

                // 需要手动DecRef
                key.DecRef()
                value.DecRef()
            }
            ---

03.常见错误
    a.忘记DecRef
        导致内存泄漏,Python对象无法释放。
    b.重复DecRef
        导致崩溃或未定义行为。
    c.使用已释放对象
        导致访问野指针,程序崩溃。

4 模块与对象

4.1 模块导入

01.导入标准库
    a.PyImport_ImportModule
        导入Python标准库模块。
    b.错误处理
        导入失败返回NULL,需检查并打印错误。
    c.导入示例
        a.功能说明
            导入并使用多个标准库模块。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 导入os模块
                osModule := python3.PyImport_ImportModule("os")
                if osModule == nil {
                    python3.PyErr_Print()
                    return
                }
                defer osModule.DecRef()

                // 获取getcwd函数
                getcwd := python3.PyObject_GetAttrString(osModule, "getcwd")
                defer getcwd.DecRef()

                emptyArgs := python3.PyTuple_New(0)
                defer emptyArgs.DecRef()

                cwd := getcwd.CallObject(emptyArgs)
                defer cwd.DecRef()

                fmt.Printf("当前目录: %s\n", python3.PyUnicode_AsUTF8(cwd))

                // 导入sys模块
                sysModule := python3.PyImport_ImportModule("sys")
                if sysModule == nil {
                    python3.PyErr_Print()
                    return
                }
                defer sysModule.DecRef()

                version := python3.PyObject_GetAttrString(sysModule, "version")
                defer version.DecRef()

                fmt.Printf("Python版本: %s\n", python3.PyUnicode_AsUTF8(version))
            }
            ---

02.导入第三方库
    a.pip安装
        需要先用pip安装第三方库。
    b.环境变量
        确保PYTHONPATH设置正确。

03.模块重载
    a.importlib.reload
        重新加载已导入的模块。
    b.重载示例
        a.功能说明
            重新加载Python模块。
        b.代码示例
            ---
            package main

            import (
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                import importlib
                import math

                print(f"math.pi = {math.pi}")

                # 模拟修改模块后重载
                importlib.reload(math)
                print(f"重载后 math.pi = {math.pi}")
                `)
            }
            ---

4.2 对象操作

01.创建对象实例
    a.获取类对象
        从模块获取类定义。
    b.调用类创建实例
        像调用函数一样调用类对象。
    c.实例创建示例
        a.功能说明
            创建Python类的实例对象。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                // 定义Python类
                python3.PyRun_SimpleString(`
                class Person:
                    def __init__(self, name, age):
                        self.name = name
                        self.age = age

                    def greet(self):
                        return f"Hello, I'm {self.name}, {self.age} years old"

                    def birthday(self):
                        self.age += 1
                        return self.age
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                personClass := python3.PyObject_GetAttrString(mainModule, "Person")
                defer personClass.DecRef()

                // 创建实例
                args := python3.PyTuple_New(2)
                defer args.DecRef()
                python3.PyTuple_SetItem(args, 0, python3.PyUnicode_FromString("Alice"))
                python3.PyTuple_SetItem(args, 1, python3.PyLong_FromGoInt(25))

                personObj := personClass.CallObject(args)
                defer personObj.DecRef()

                // 调用方法
                greetMethod := python3.PyObject_GetAttrString(personObj, "greet")
                defer greetMethod.DecRef()

                emptyArgs := python3.PyTuple_New(0)
                defer emptyArgs.DecRef()

                greeting := greetMethod.CallObject(emptyArgs)
                defer greeting.DecRef()

                fmt.Println(python3.PyUnicode_AsUTF8(greeting))
            }
            ---

02.对象类型检查
    a.PyObject_Type
        获取对象的类型。
    b.PyObject_IsInstance
        检查对象是否为特定类的实例。

03.对象比较
    a.PyObject_RichCompare
        比较两个Python对象。
    b.比较运算符
        支持<、<=、==、!=、>、>=等运算符。

4.3 属性访问

01.获取属性
    a.PyObject_GetAttrString
        通过字符串名称获取对象属性。
    b.PyObject_GetAttr
        通过Python对象获取属性。
    c.属性获取示例
        a.功能说明
            获取和修改Python对象的属性。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                class Car:
                    def __init__(self, brand, year):
                        self.brand = brand
                        self.year = year
                        self.mileage = 0

                    def drive(self, km):
                        self.mileage += km

                car = Car("Toyota", 2020)
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                car := python3.PyObject_GetAttrString(mainModule, "car")
                defer car.DecRef()

                // 获取属性
                brand := python3.PyObject_GetAttrString(car, "brand")
                defer brand.DecRef()
                fmt.Printf("品牌: %s\n", python3.PyUnicode_AsUTF8(brand))

                year := python3.PyObject_GetAttrString(car, "year")
                defer year.DecRef()
                fmt.Printf("年份: %d\n", python3.PyLong_AsLong(year))

                // 修改属性
                newMileage := python3.PyLong_FromGoInt(5000)
                python3.PyObject_SetAttrString(car, "mileage", newMileage)
                newMileage.DecRef()

                mileage := python3.PyObject_GetAttrString(car, "mileage")
                defer mileage.DecRef()
                fmt.Printf("里程: %d km\n", python3.PyLong_AsLong(mileage))
            }
            ---

02.设置属性
    a.PyObject_SetAttrString
        设置对象属性值。
    b.动态添加
        可以动态添加新属性到对象。

03.删除属性
    a.PyObject_DelAttrString
        删除对象的指定属性。
    b.属性检查
        使用PyObject_HasAttrString检查属性是否存在。

4.4 方法调用

01.调用实例方法
    a.获取方法对象
        使用GetAttrString获取方法。
    b.传递参数
        使用tuple传递方法参数。
    c.方法调用示例
        a.功能说明
            调用Python对象的实例方法。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                class Calculator:
                    def __init__(self):
                        self.result = 0

                    def add(self, x, y):
                        self.result = x + y
                        return self.result

                    def multiply(self, x, y):
                        self.result = x * y
                        return self.result

                    def get_result(self):
                        return self.result

                calc = Calculator()
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                calc := python3.PyObject_GetAttrString(mainModule, "calc")
                defer calc.DecRef()

                // 调用add方法
                addMethod := python3.PyObject_GetAttrString(calc, "add")
                defer addMethod.DecRef()

                args := python3.PyTuple_New(2)
                python3.PyTuple_SetItem(args, 0, python3.PyLong_FromGoInt(10))
                python3.PyTuple_SetItem(args, 1, python3.PyLong_FromGoInt(20))

                result := addMethod.CallObject(args)
                defer result.DecRef()
                defer args.DecRef()

                fmt.Printf("10 + 20 = %d\n", python3.PyLong_AsLong(result))

                // 调用multiply方法
                multiplyMethod := python3.PyObject_GetAttrString(calc, "multiply")
                defer multiplyMethod.DecRef()

                args2 := python3.PyTuple_New(2)
                python3.PyTuple_SetItem(args2, 0, python3.PyLong_FromGoInt(5))
                python3.PyTuple_SetItem(args2, 1, python3.PyLong_FromGoInt(6))

                result2 := multiplyMethod.CallObject(args2)
                defer result2.DecRef()
                defer args2.DecRef()

                fmt.Printf("5 * 6 = %d\n", python3.PyLong_AsLong(result2))
            }
            ---

02.调用静态方法
    a.静态方法定义
        使用@staticmethod装饰器。
    b.无需实例
        可以直接从类调用静态方法。

03.调用类方法
    a.类方法定义
        使用@classmethod装饰器。
    b.接收类对象
        第一个参数自动为类对象。

4.5 异常处理

01.检查异常
    a.PyErr_Occurred
        检查是否发生异常。
    b.返回NULL
        发生异常时API返回NULL。
    c.异常检查示例
        a.功能说明
            检测和处理Python异常。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func safeDivide(a, b int) {
                python3.PyRun_SimpleString(fmt.Sprintf(`
                try:
                    result = %d / %d
                    print(f"结果: {result}")
                except ZeroDivisionError as e:
                    print(f"除零错误: {e}")
                except Exception as e:
                    print(f"其他错误: {e}")
                `, a, b))
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                safeDivide(10, 2)
                safeDivide(10, 0)
            }
            ---

02.打印异常
    a.PyErr_Print
        打印异常信息到stderr并清除异常状态。
    b.PyErr_Clear
        仅清除异常状态,不打印。
    c.异常打印示例
        a.功能说明
            正确处理和打印Python异常信息。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func callPythonFunc(funcName string) {
                mainModule := python3.PyImport_AddModule("__main__")
                fn := python3.PyObject_GetAttrString(mainModule, funcName)

                if fn == nil {
                    fmt.Printf("函数 '%s' 不存在\n", funcName)
                    if python3.PyErr_Occurred() != nil {
                        python3.PyErr_Print()
                    }
                    return
                }
                defer fn.DecRef()

                args := python3.PyTuple_New(0)
                defer args.DecRef()

                result := fn.CallObject(args)
                if result == nil {
                    fmt.Printf("调用 '%s' 时发生异常:\n", funcName)
                    python3.PyErr_Print()
                    return
                }
                defer result.DecRef()

                fmt.Printf("'%s' 执行成功\n", funcName)
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                def good_func():
                    return "OK"

                def bad_func():
                    raise ValueError("Something went wrong")
                `)

                callPythonFunc("good_func")
                callPythonFunc("bad_func")
                callPythonFunc("nonexistent_func")
            }
            ---

03.获取异常信息
    a.PyErr_Fetch
        获取异常类型、值和traceback。
    b.PyErr_NormalizeException
        规范化异常对象。

5 高级特性

5.1 多线程处理

01.多线程基础
    a.GIL限制
        同一时刻只有一个线程执行Python代码。
    b.runtime.LockOSThread
        将goroutine绑定到OS线程。

02.多线程示例
    a.功能说明
        在多个goroutine中并发调用Python。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "runtime"
            "sync"
            python3 "github.com/DataDog/go-python3"
        )

        func pythonWorker(id int, wg *sync.WaitGroup) {
            defer wg.Done()

            runtime.LockOSThread()
            defer runtime.UnlockOSThread()

            gilState := python3.PyGILState_Ensure()
            defer python3.PyGILState_Release(gilState)

            code := fmt.Sprintf(`
            import time
            start = time.time()
            result = sum([i**2 for i in range(100000)])
            elapsed = time.time() - start
            print(f"Worker {%d}: result={result}, time={elapsed:.4f}s")
            `, id)

            python3.PyRun_SimpleString(code)
        }

        func main() {
            runtime.LockOSThread()
            python3.Py_Initialize()
            defer python3.Py_Finalize()

            var wg sync.WaitGroup
            for i := 0; i < 4; i++ {
                wg.Add(1)
                go pythonWorker(i, &wg)
            }
            wg.Wait()
            fmt.Println("所有worker完成")
        }
        ---

03.线程同步
    a.使用channel
        通过Go channel协调多个Python调用。
    b.使用mutex
        保护共享的Python对象。

5.2 GIL管理

01.PyGILState_Ensure
    a.功能说明
        在当前线程获取GIL,确保可以调用Python API。
    b.返回值
        返回GIL状态,需要传递给Release。

02.PyGILState_Release
    a.功能说明
        释放之前获取的GIL。
    b.参数
        需要传入Ensure返回的状态值。

03.GIL管理示例
    a.功能说明
        正确的GIL获取和释放流程。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "runtime"
            "time"
            python3 "github.com/DataDog/go-python3"
        )

        func longRunningTask(taskID int) {
            runtime.LockOSThread()
            defer runtime.UnlockOSThread()

            gilState := python3.PyGILState_Ensure()

            python3.PyRun_SimpleString(fmt.Sprintf(`
            print("Task %d: 获取GIL")
            import time
            time.sleep(0.1)
            print("Task %d: Python计算中...")
            result = sum(range(1000000))
            print(f"Task {%d}: 完成,结果={result}")
            `, taskID, taskID, taskID))

            python3.PyGILState_Release(gilState)
        }

        func main() {
            python3.Py_Initialize()
            defer python3.Py_Finalize()

            done := make(chan bool)

            for i := 0; i < 3; i++ {
                taskID := i
                go func() {
                    longRunningTask(taskID)
                    done <- true
                }()
                time.Sleep(10 * time.Millisecond)
            }

            for i := 0; i < 3; i++ {
                <-done
            }
            fmt.Println("所有任务完成")
        }
        ---

04.释放GIL执行Go代码
    a.PyEval_SaveThread
        释放GIL,允许其他线程执行。
    b.PyEval_RestoreThread
        重新获取GIL。

5.3 回调函数

01.Go回调Python
    a.定义回调
        在Python中定义回调函数,从Go调用。
    b.传递回调
        a.功能说明
            将Go函数包装后传递给Python作为回调。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                def process_data(data, callback):
                    result = data * 2
                    return callback(result)

                def my_callback(value):
                    return value + 100
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                processFunc := python3.PyObject_GetAttrString(mainModule, "process_data")
                defer processFunc.DecRef()

                callbackFunc := python3.PyObject_GetAttrString(mainModule, "my_callback")
                defer callbackFunc.DecRef()

                args := python3.PyTuple_New(2)
                defer args.DecRef()
                python3.PyTuple_SetItem(args, 0, python3.PyLong_FromGoInt(50))
                python3.PyTuple_SetItem(args, 1, callbackFunc)
                callbackFunc.IncRef()

                result := processFunc.CallObject(args)
                defer result.DecRef()

                fmt.Printf("回调结果: %d\n", python3.PyLong_AsLong(result))
            }
            ---

02.闭包回调
    a.捕获变量
        Python闭包可以捕获外部变量。
    b.闭包示例
        a.功能说明
            使用闭包实现带状态的回调函数。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                def create_counter():
                    count = 0
                    def counter():
                        nonlocal count
                        count += 1
                        return count
                    return counter

                def apply_n_times(func, n):
                    results = []
                    for _ in range(n):
                        results.append(func())
                    return results
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                createCounter := python3.PyObject_GetAttrString(mainModule, "create_counter")
                defer createCounter.DecRef()

                emptyArgs := python3.PyTuple_New(0)
                defer emptyArgs.DecRef()

                counter := createCounter.CallObject(emptyArgs)
                defer counter.DecRef()

                applyFunc := python3.PyObject_GetAttrString(mainModule, "apply_n_times")
                defer applyFunc.DecRef()

                args := python3.PyTuple_New(2)
                defer args.DecRef()
                python3.PyTuple_SetItem(args, 0, counter)
                counter.IncRef()
                python3.PyTuple_SetItem(args, 1, python3.PyLong_FromGoInt(5))

                results := applyFunc.CallObject(args)
                defer results.DecRef()

                size := python3.PyList_Size(results)
                fmt.Print("计数结果: [")
                for i := 0; i < size; i++ {
                    item := python3.PyList_GetItem(results, i)
                    if i > 0 {
                        fmt.Print(", ")
                    }
                    fmt.Print(python3.PyLong_AsLong(item))
                }
                fmt.Println("]")
            }
            ---

03.异步回调
    a.延迟执行
        回调函数可以在异步操作完成后执行。
    b.事件处理
        使用回调实现事件驱动编程模式。

5.4 子解释器

01.子解释器概念
    a.隔离环境
        子解释器提供独立的Python执行环境。
    b.资源隔离
        每个子解释器有独立的模块、全局变量。

02.创建子解释器
    a.Py_NewInterpreter
        创建新的子解释器实例。
    b.子解释器示例
        a.功能说明
            创建独立的子解释器执行不同代码。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                "runtime"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                runtime.LockOSThread()
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                mainState := python3.PyEval_SaveThread()

                python3.PyEval_RestoreThread(mainState)
                python3.PyRun_SimpleString("main_var = 'main'")
                python3.PyRun_SimpleString("print(f'主解释器: {main_var}')")

                subState := python3.Py_NewInterpreter()
                if subState == nil {
                    fmt.Println("创建子解释器失败")
                    return
                }

                python3.PyRun_SimpleString("sub_var = 'sub'")
                python3.PyRun_SimpleString("print(f'子解释器: {sub_var}')")

                python3.Py_EndInterpreter(subState)

                python3.PyRun_SimpleString("print(f'返回主解释器: {main_var}')")
            }
            ---

03.子解释器通信
    a.数据传递
        通过序列化在不同解释器间传递数据。
    b.通信示例
        a.功能说明
            使用pickle在子解释器间传递对象。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                import pickle

                def serialize_data(data):
                    return pickle.dumps(data)

                def deserialize_data(data_bytes):
                    return pickle.loads(data_bytes)

                shared_data = {'key': 'value', 'number': 42}
                serialized = serialize_data(shared_data)
                print(f"序列化数据: {len(serialized)} bytes")

                restored = deserialize_data(serialized)
                print(f"反序列化数据: {restored}")
                `)

                fmt.Println("子解释器通信完成")
            }
            ---

04.子解释器限制
    a.GIL共享
        所有子解释器共享同一个GIL。
    b.扩展模块
        部分C扩展模块可能不支持子解释器。

5.5 性能优化

01.减少对象创建
    a.对象复用
        重复使用Python对象减少创建销毁开销。
    b.复用示例
        a.功能说明
            缓存常用对象避免重复创建。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                "time"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                def add(a, b):
                    return a + b
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                addFunc := python3.PyObject_GetAttrString(mainModule, "add")
                defer addFunc.DecRef()

                emptyKwargs := python3.PyDict_New()
                defer emptyKwargs.DecRef()

                start := time.Now()
                for i := 0; i < 10000; i++ {
                    args := python3.PyTuple_New(2)
                    python3.PyTuple_SetItem(args, 0, python3.PyLong_FromGoInt(i))
                    python3.PyTuple_SetItem(args, 1, python3.PyLong_FromGoInt(i+1))
                    result := addFunc.Call(args, emptyKwargs)
                    result.DecRef()
                    args.DecRef()
                }
                fmt.Printf("10000次调用耗时: %v\n", time.Since(start))
            }
            ---

02.批量处理
    a.减少调用次数
        批量处理数据减少Go-Python边界跨越。
    b.批量示例
        a.功能说明
            一次传递多个数据进行批量计算。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                "time"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                def process_batch(numbers):
                    return [n * 2 for n in numbers]

                def process_single(n):
                    return n * 2
                `)

                mainModule := python3.PyImport_AddModule("__main__")

                processBatch := python3.PyObject_GetAttrString(mainModule, "process_batch")
                defer processBatch.DecRef()

                pyList := python3.PyList_New(1000)
                for i := 0; i < 1000; i++ {
                    python3.PyList_SetItem(pyList, i, python3.PyLong_FromGoInt(i))
                }

                args := python3.PyTuple_New(1)
                python3.PyTuple_SetItem(args, 0, pyList)

                start := time.Now()
                result := processBatch.CallObject(args)
                fmt.Printf("批量处理1000个数耗时: %v\n", time.Since(start))

                result.DecRef()
                args.DecRef()
            }
            ---

03.使用C扩展
    a.NumPy优化
        使用NumPy等C扩展库提升计算性能。
    b.避免纯Python循环
        将密集计算移至C扩展或Go实现。

6 实战应用

6.1 安装配置

01.环境要求
    a.Python版本
        需要Python 3.x(推荐3.7+)。
    b.CGO支持
        必须启用CGO编译支持。

02.安装go-python3
    a.获取依赖
        使用go get命令获取库。
    b.安装示例
        a.功能说明
            通过go get安装go-python3库。
        b.代码示例
            ---
            go get -u github.com/DataDog/go-python3
            ---
    c.pkg-config配置
        确保pkg-config能找到python3。
    d.配置示例
        a.功能说明
            验证pkg-config配置是否正确。
        b.代码示例
            ---
            pkg-config --cflags --libs python3
            pkg-config --modversion python3
            ---

03.编译配置
    a.CGO_ENABLED
        设置CGO_ENABLED=1启用CGO。
    b.编译示例
        a.功能说明
            正确编译使用go-python3的程序。
        b.代码示例
            ---
            CGO_ENABLED=1 go build main.go
            ---

04.常见问题
    a.找不到Python
        设置PKG_CONFIG_PATH指向python3.pc文件。
    b.链接错误
        检查Python开发包是否已安装。
    c.解决示例
        a.功能说明
            排查和解决常见安装问题。
        b.代码示例
            ---
            export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
            export CGO_CFLAGS="-I/usr/include/python3.9"
            export CGO_LDFLAGS="-L/usr/lib -lpython3.9"
            go build
            ---

6.2 调用NumPy

01.NumPy简介
    a.科学计算
        NumPy提供高性能数组和数学函数。
    b.C扩展
        NumPy底层使用C实现,性能优异。

02.调用NumPy数组
    a.导入NumPy
        使用PyImport_ImportModule导入numpy。
    b.数组操作
        a.功能说明
            创建NumPy数组并执行计算。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                numpy := python3.PyImport_ImportModule("numpy")
                if numpy == nil {
                    python3.PyErr_Print()
                    return
                }
                defer numpy.DecRef()

                arrayFunc := python3.PyObject_GetAttrString(numpy, "array")
                defer arrayFunc.DecRef()

                pyList := python3.PyList_New(5)
                for i := 0; i < 5; i++ {
                    python3.PyList_SetItem(pyList, i, python3.PyLong_FromGoInt(i*10))
                }

                args := python3.PyTuple_New(1)
                python3.PyTuple_SetItem(args, 0, pyList)

                npArray := arrayFunc.CallObject(args)
                defer npArray.DecRef()
                defer args.DecRef()

                meanFunc := python3.PyObject_GetAttrString(npArray, "mean")
                defer meanFunc.DecRef()

                emptyArgs := python3.PyTuple_New(0)
                defer emptyArgs.DecRef()

                meanResult := meanFunc.CallObject(emptyArgs)
                defer meanResult.DecRef()

                fmt.Printf("NumPy数组均值: %.2f\n", python3.PyFloat_AsDouble(meanResult))
            }
            ---

03.矩阵运算
    a.矩阵乘法
        使用np.dot进行矩阵运算。
    b.矩阵示例
        a.功能说明
            执行NumPy矩阵乘法运算。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                import numpy as np

                def matrix_multiply(a, b):
                    arr_a = np.array(a)
                    arr_b = np.array(b)
                    result = np.dot(arr_a, arr_b)
                    return result.tolist()
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                matMul := python3.PyObject_GetAttrString(mainModule, "matrix_multiply")
                defer matMul.DecRef()

                matA := python3.PyList_New(2)
                rowA1 := python3.PyList_New(2)
                python3.PyList_SetItem(rowA1, 0, python3.PyLong_FromGoInt(1))
                python3.PyList_SetItem(rowA1, 1, python3.PyLong_FromGoInt(2))
                rowA2 := python3.PyList_New(2)
                python3.PyList_SetItem(rowA2, 0, python3.PyLong_FromGoInt(3))
                python3.PyList_SetItem(rowA2, 1, python3.PyLong_FromGoInt(4))
                python3.PyList_SetItem(matA, 0, rowA1)
                python3.PyList_SetItem(matA, 1, rowA2)

                matB := python3.PyList_New(2)
                rowB1 := python3.PyList_New(2)
                python3.PyList_SetItem(rowB1, 0, python3.PyLong_FromGoInt(5))
                python3.PyList_SetItem(rowB1, 1, python3.PyLong_FromGoInt(6))
                rowB2 := python3.PyList_New(2)
                python3.PyList_SetItem(rowB2, 0, python3.PyLong_FromGoInt(7))
                python3.PyList_SetItem(rowB2, 1, python3.PyLong_FromGoInt(8))
                python3.PyList_SetItem(matB, 0, rowB1)
                python3.PyList_SetItem(matB, 1, rowB2)

                args := python3.PyTuple_New(2)
                python3.PyTuple_SetItem(args, 0, matA)
                python3.PyTuple_SetItem(args, 1, matB)

                result := matMul.CallObject(args)
                defer result.DecRef()
                defer args.DecRef()

                fmt.Println("矩阵乘法结果:")
                size := python3.PyList_Size(result)
                for i := 0; i < size; i++ {
                    row := python3.PyList_GetItem(result, i)
                    rowSize := python3.PyList_Size(row)
                    for j := 0; j < rowSize; j++ {
                        item := python3.PyList_GetItem(row, j)
                        fmt.Printf("%d ", python3.PyLong_AsLong(item))
                    }
                    fmt.Println()
                }
            }
            ---

04.性能优化
    a.避免转换
        尽量在Python侧完成批量计算。
    b.使用视图
        NumPy视图避免数据复制。

6.3 机器学习库

01.调用scikit-learn
    a.模型训练
        使用sklearn训练机器学习模型。
    b.训练示例
        a.功能说明
            训练简单线性回归模型。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                from sklearn.linear_model import LinearRegression
                import numpy as np

                def train_model(X_data, y_data):
                    model = LinearRegression()
                    X = np.array(X_data).reshape(-1, 1)
                    y = np.array(y_data)
                    model.fit(X, y)
                    return model.coef_[0], model.intercept_

                def predict(coef, intercept, X_data):
                    X = np.array(X_data).reshape(-1, 1)
                    return (X * coef + intercept).tolist()
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                trainFunc := python3.PyObject_GetAttrString(mainModule, "train_model")
                defer trainFunc.DecRef()

                X := python3.PyList_New(5)
                y := python3.PyList_New(5)
                for i := 0; i < 5; i++ {
                    python3.PyList_SetItem(X, i, python3.PyFloat_FromDouble(float64(i)))
                    python3.PyList_SetItem(y, i, python3.PyFloat_FromDouble(float64(i*2+1)))
                }

                args := python3.PyTuple_New(2)
                python3.PyTuple_SetItem(args, 0, X)
                python3.PyTuple_SetItem(args, 1, y)

                result := trainFunc.CallObject(args)
                defer result.DecRef()
                defer args.DecRef()

                coef := python3.PyTuple_GetItem(result, 0)
                intercept := python3.PyTuple_GetItem(result, 1)

                fmt.Printf("训练完成 - 系数: %.2f, 截距: %.2f\n",
                    python3.PyFloat_AsDouble(coef),
                    python3.PyFloat_AsDouble(intercept))
            }
            ---

02.调用TensorFlow
    a.模型加载
        加载预训练的TensorFlow模型。
    b.推理示例
        a.功能说明
            使用TensorFlow进行模型推理。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                import numpy as np

                def simple_nn_predict(input_data):
                    # 模拟简单神经网络预测
                    data = np.array(input_data)
                    weights = np.array([0.5, 0.3, 0.2])
                    result = np.dot(data, weights)
                    return float(result)
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                predictFunc := python3.PyObject_GetAttrString(mainModule, "simple_nn_predict")
                defer predictFunc.DecRef()

                inputData := python3.PyList_New(3)
                python3.PyList_SetItem(inputData, 0, python3.PyFloat_FromDouble(1.0))
                python3.PyList_SetItem(inputData, 1, python3.PyFloat_FromDouble(2.0))
                python3.PyList_SetItem(inputData, 2, python3.PyFloat_FromDouble(3.0))

                args := python3.PyTuple_New(1)
                python3.PyTuple_SetItem(args, 0, inputData)

                result := predictFunc.CallObject(args)
                defer result.DecRef()
                defer args.DecRef()

                fmt.Printf("神经网络预测结果: %.4f\n", python3.PyFloat_AsDouble(result))
            }
            ---

03.批量推理
    a.批量处理
        一次传递多个样本进行批量推理。
    b.性能优化
        批量推理减少Python调用次数,提升性能。

6.4 数据处理

01.Pandas数据分析
    a.DataFrame操作
        使用Pandas进行数据分析和处理。
    b.DataFrame示例
        a.功能说明
            创建并操作Pandas DataFrame。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                import pandas as pd

                def create_dataframe(data_dict):
                    df = pd.DataFrame(data_dict)
                    return df

                def analyze_dataframe(df):
                    stats = {
                        'mean': df.mean().to_dict(),
                        'max': df.max().to_dict(),
                        'min': df.min().to_dict()
                    }
                    return stats
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                createDF := python3.PyObject_GetAttrString(mainModule, "create_dataframe")
                defer createDF.DecRef()

                dataDict := python3.PyDict_New()

                ageList := python3.PyList_New(5)
                for i := 0; i < 5; i++ {
                    python3.PyList_SetItem(ageList, i, python3.PyLong_FromGoInt(20+i*5))
                }
                python3.PyDict_SetItemString(dataDict, "age", ageList)

                scoreList := python3.PyList_New(5)
                scores := []int{85, 90, 88, 92, 87}
                for i, s := range scores {
                    python3.PyList_SetItem(scoreList, i, python3.PyLong_FromGoInt(s))
                }
                python3.PyDict_SetItemString(dataDict, "score", scoreList)

                args := python3.PyTuple_New(1)
                python3.PyTuple_SetItem(args, 0, dataDict)

                df := createDF.CallObject(args)
                defer df.DecRef()
                defer args.DecRef()

                analyzeFunc := python3.PyObject_GetAttrString(mainModule, "analyze_dataframe")
                defer analyzeFunc.DecRef()

                analyzeArgs := python3.PyTuple_New(1)
                python3.PyTuple_SetItem(analyzeArgs, 0, df)
                df.IncRef()

                stats := analyzeFunc.CallObject(analyzeArgs)
                defer stats.DecRef()
                defer analyzeArgs.DecRef()

                fmt.Println("DataFrame统计分析完成")
            }
            ---

02.数据清洗
    a.缺失值处理
        使用fillna、dropna处理缺失数据。
    b.清洗示例
        a.功能说明
            清洗包含缺失值的数据。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                import pandas as pd
                import numpy as np

                def clean_data(data_list):
                    df = pd.DataFrame(data_list, columns=['value'])
                    df_cleaned = df.fillna(df['value'].mean())
                    return df_cleaned['value'].tolist()
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                cleanFunc := python3.PyObject_GetAttrString(mainModule, "clean_data")
                defer cleanFunc.DecRef()

                dataList := python3.PyList_New(6)
                values := []float64{1.0, 2.0, -1.0, 4.0, 5.0, -1.0}
                for i, v := range values {
                    if v < 0 {
                        python3.PyList_SetItem(dataList, i, python3.Py_None)
                    } else {
                        python3.PyList_SetItem(dataList, i, python3.PyFloat_FromDouble(v))
                    }
                }

                args := python3.PyTuple_New(1)
                python3.PyTuple_SetItem(args, 0, dataList)

                result := cleanFunc.CallObject(args)
                defer result.DecRef()
                defer args.DecRef()

                fmt.Print("清洗后数据: [")
                size := python3.PyList_Size(result)
                for i := 0; i < size; i++ {
                    if i > 0 {
                        fmt.Print(", ")
                    }
                    item := python3.PyList_GetItem(result, i)
                    fmt.Printf("%.2f", python3.PyFloat_AsDouble(item))
                }
                fmt.Println("]")
            }
            ---

03.数据转换
    a.格式转换
        CSV、JSON、Excel等格式互转。
    b.聚合计算
        groupby分组统计数据。

6.5 脚本执行

01.执行Python脚本文件
    a.PyRun_SimpleFile
        从文件执行Python脚本。
    b.文件执行示例
        a.功能说明
            读取并执行外部Python脚本文件。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                "os"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                scriptContent := `
                def greet(name):
                    return f"Hello, {name}!"

                def calculate(a, b):
                    return a + b

                result = greet("World")
                print(result)
                sum_result = calculate(10, 20)
                print(f"Sum: {sum_result}")
                `

                tmpFile, err := os.CreateTemp("", "script*.py")
                if err != nil {
                    fmt.Printf("创建临时文件失败: %v\n", err)
                    return
                }
                defer os.Remove(tmpFile.Name())

                _, err = tmpFile.WriteString(scriptContent)
                if err != nil {
                    fmt.Printf("写入文件失败: %v\n", err)
                    return
                }
                tmpFile.Close()

                file, err := os.Open(tmpFile.Name())
                if err != nil {
                    fmt.Printf("打开文件失败: %v\n", err)
                    return
                }
                defer file.Close()

                python3.PyRun_SimpleFile(file, tmpFile.Name())
                fmt.Println("脚本执行完成")
            }
            ---

02.动态脚本执行
    a.运行时生成
        根据条件动态生成并执行Python代码。
    b.动态执行示例
        a.功能说明
            动态生成Python代码并执行。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func executeDynamicScript(operation string, a, b int) {
                var script string
                switch operation {
                case "add":
                    script = fmt.Sprintf("result = %d + %d", a, b)
                case "multiply":
                    script = fmt.Sprintf("result = %d * %d", a, b)
                case "power":
                    script = fmt.Sprintf("result = %d ** %d", a, b)
                default:
                    script = "result = 0"
                }

                python3.PyRun_SimpleString(script)

                mainModule := python3.PyImport_AddModule("__main__")
                resultObj := python3.PyObject_GetAttrString(mainModule, "result")
                defer resultObj.DecRef()

                result := python3.PyLong_AsLong(resultObj)
                fmt.Printf("%s(%d, %d) = %d\n", operation, a, b, result)
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                executeDynamicScript("add", 10, 20)
                executeDynamicScript("multiply", 5, 6)
                executeDynamicScript("power", 2, 8)
            }
            ---

03.脚本安全
    a.输入验证
        验证脚本输入防止注入攻击。
    b.沙箱执行
        使用受限环境执行不受信任的代码。
    c.安全示例
        a.功能说明
            在受限环境中安全执行Python代码。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                import sys
                restricted_builtins = {
                    'print': print,
                    'len': len,
                    'range': range,
                    'sum': sum,
                }

                def safe_exec(code_str):
                    try:
                        exec(code_str, {"__builtins__": restricted_builtins})
                        return "执行成功"
                    except Exception as e:
                        return f"执行失败: {str(e)}"
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                safeExec := python3.PyObject_GetAttrString(mainModule, "safe_exec")
                defer safeExec.DecRef()

                safeCode := "print(sum(range(10)))"
                unsafeCode := "import os; os.system('ls')"

                for _, code := range []string{safeCode, unsafeCode} {
                    args := python3.PyTuple_New(1)
                    python3.PyTuple_SetItem(args, 0, python3.PyUnicode_FromString(code))

                    result := safeExec.CallObject(args)
                    resultStr := python3.PyUnicode_AsUTF8(result)
                    fmt.Printf("代码: %s -> %s\n", code, resultStr)

                    result.DecRef()
                    args.DecRef()
                }
            }
            ---

6.6 常见问题

01.内存泄漏
    a.引用计数错误
        未正确DecRef导致对象无法释放。
    b.检测方法
        a.功能说明
            使用Python gc模块检测内存泄漏。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                python3.PyRun_SimpleString(`
                import gc
                import sys

                def check_memory():
                    gc.collect()
                    return len(gc.get_objects())
                `)

                mainModule := python3.PyImport_AddModule("__main__")
                checkMem := python3.PyObject_GetAttrString(mainModule, "check_memory")
                defer checkMem.DecRef()

                emptyArgs := python3.PyTuple_New(0)
                defer emptyArgs.DecRef()

                beforeCount := checkMem.CallObject(emptyArgs)
                beforeVal := python3.PyLong_AsLong(beforeCount)
                beforeCount.DecRef()

                for i := 0; i < 1000; i++ {
                    obj := python3.PyLong_FromGoInt(i)
                    obj.DecRef()
                }

                afterCount := checkMem.CallObject(emptyArgs)
                afterVal := python3.PyLong_AsLong(afterCount)
                afterCount.DecRef()

                fmt.Printf("对象数 - 前: %d, 后: %d\n", beforeVal, afterVal)
            }
            ---

02.GIL死锁
    a.死锁原因
        多个goroutine竞争GIL导致死锁。
    b.避免策略
        正确使用PyGILState_Ensure/Release和LockOSThread。
    c.解决示例
        a.功能说明
            正确的多线程调用模式避免死锁。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                "runtime"
                "sync"
                python3 "github.com/DataDog/go-python3"
            )

            func safeWorker(id int, wg *sync.WaitGroup) {
                defer wg.Done()
                runtime.LockOSThread()
                defer runtime.UnlockOSThread()

                gilState := python3.PyGILState_Ensure()
                defer python3.PyGILState_Release(gilState)

                code := fmt.Sprintf(`
                import time
                time.sleep(0.001)
                print("Worker %d done")
                `, id)
                python3.PyRun_SimpleString(code)
            }

            func main() {
                runtime.LockOSThread()
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                var wg sync.WaitGroup
                for i := 0; i < 10; i++ {
                    wg.Add(1)
                    go safeWorker(i, &wg)
                }
                wg.Wait()

                fmt.Println("所有worker完成,无死锁")
            }
            ---

03.类型转换错误
    a.类型检查
        调用前检查Python对象类型。
    b.错误处理
        转换失败时正确处理异常。
    c.处理示例
        a.功能说明
            安全的类型转换与错误处理。
        b.代码示例
            ---
            package main

            import (
                "fmt"
                python3 "github.com/DataDog/go-python3"
            )

            func safeConvertToInt(obj *python3.PyObject) (int, error) {
                if !python3.PyLong_Check(obj) {
                    if python3.PyFloat_Check(obj) {
                        floatVal := python3.PyFloat_AsDouble(obj)
                        return int(floatVal), nil
                    }
                    return 0, fmt.Errorf("对象不是整数或浮点数")
                }
                return python3.PyLong_AsLong(obj), nil
            }

            func main() {
                python3.Py_Initialize()
                defer python3.Py_Finalize()

                intObj := python3.PyLong_FromGoInt(42)
                defer intObj.DecRef()

                floatObj := python3.PyFloat_FromDouble(3.14)
                defer floatObj.DecRef()

                strObj := python3.PyUnicode_FromString("hello")
                defer strObj.DecRef()

                for i, obj := range []*python3.PyObject{intObj, floatObj, strObj} {
                    val, err := safeConvertToInt(obj)
                    if err != nil {
                        fmt.Printf("对象%d转换失败: %v\n", i, err)
                    } else {
                        fmt.Printf("对象%d转换成功: %d\n", i, val)
                    }
                }
            }
            ---

04.性能问题
    a.频繁跨语言调用
        减少Go-Python边界跨越次数。
    b.批量处理
        使用批量操作代替循环调用。