![]() |
VOOZH | about |
dotnet add package GoesSoftware.SuperSDK.Python --version 7.23.7
NuGet\Install-Package GoesSoftware.SuperSDK.Python -Version 7.23.7
<PackageReference Include="GoesSoftware.SuperSDK.Python" Version="7.23.7" />
<PackageVersion Include="GoesSoftware.SuperSDK.Python" Version="7.23.7" />Directory.Packages.props
<PackageReference Include="GoesSoftware.SuperSDK.Python" />Project file
paket add GoesSoftware.SuperSDK.Python --version 7.23.7
#r "nuget: GoesSoftware.SuperSDK.Python, 7.23.7"
#:package GoesSoftware.SuperSDK.Python@7.23.7
#addin nuget:?package=GoesSoftware.SuperSDK.Python&version=7.23.7Install as a Cake Addin
#tool nuget:?package=GoesSoftware.SuperSDK.Python&version=7.23.7Install as a Cake Tool
SuperSDK Python 进程桥接库,适用于 .NET 9 / Avalonia 桌面应用。
无需额外 Python 包(仅标准库),new GzPythonWrapper() 自动完成进程启动与连接。
内置 GzPyConsoleCtrl Avalonia 控件,一行 AXAML 即可展示实时日志、状态、心跳 —— 不需要在 ViewModel 中声明任何额外字段。
dotnet add package GoesSoftware.SuperSDK.Python
using ReactiveUI;
using SuperSDK.Python;
public class MainWindowViewModel : ReactiveObject
{
private MyWrapper? _py;
public MyWrapper? Py { get => _py; private set => this.RaiseAndSetIfChanged(ref _py, value); }
// 启动
private Task StartAsync()
{
if (Py != null) return Task.CompletedTask;
Py = new MyWrapper(); // 自动启动 Python 进程
return Task.CompletedTask;
}
// 释放
private async Task ReleaseAsync()
{
var py = Py; Py = null;
if (py != null) await Task.Run(() => py.Dispose());
}
}
<Window xmlns="https://github.com/avaloniaui"
xmlns:pyctrl="clr-namespace:SuperSDK.Python.Controls;assembly=SuperSDK.Python">
<TextBlock Text="{Binding Py.Status, FallbackValue=未启动}"/>
<TextBlock Text="{Binding Py.LastHeartbeat, FallbackValue=-}"/>
<pyctrl:GzPyConsoleCtrl WrapperId="{Binding Py.Id}" Height="200"/>
</Window>
就是这样。 ViewModel 不需要 PyStatus、PyHeartbeat、PyWrapperId 等任何中转属性。
GzPythonWrapper 实现了 INotifyPropertyChanged,Avalonia 绑定引擎直接感知其变化。
Python 侧(PythonScripts/my_service.py):
from gz_sdk import rpc_method, gz_service, publish
@gz_service
class MyService:
@rpc_method # ← 必须加,gz_service 只注册此装饰器标记的方法
def process(self, params):
req_id = params.get("__request_id")
publish(data="处理中 50%", request_id=req_id)
publish(data="处理完成", request_id=req_id)
C# 侧(MyWrapper.cs):
using SuperSDK.Python;
public class MyWrapper : GzPythonWrapper
{
public Task<GzResult> ProcessAsync(string input)
=> CallAsync("process", new { P1 = input });
}
csproj(必须将 PythonScripts 嵌入 DLL):
<ItemGroup>
<EmbeddedResource Include="PythonScripts\**\*.py" />
</ItemGroup>
基类约定会在启动时沿继承链扫描各程序集的 PythonScripts/ 嵌入资源,自动解包到 Python 工作目录,无需任何 override。
结果通过 GzPythonLogMsg(level = Progress)自动送达 GzPyConsoleCtrl,无需手动处理。
Python 调用 publish() 推送的事件,除了自动显示在 GzPyConsoleCtrl 外,也可以在 C# 中主动订阅:
// 订阅 "progress" 事件(publish() / publish_event("progress", ...) 推送)
py.Subscribe("progress", msg =>
{
Console.WriteLine($"[{msg.RequestId}] {msg.Data}");
});
// 订阅自定义命名事件(publish_event("done", ...) 推送)
py.Subscribe("done", msg =>
{
Console.WriteLine("任务完成!");
});
// 订阅心跳(每 10 秒由 gz_core.py 自动推送)
py.Subscribe("heartbeat", msg =>
{
Console.WriteLine($"心跳: {msg.Data}");
});
GzEventMessage 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
EventName |
string |
事件名("progress" / "heartbeat" / 自定义) |
Data |
string |
事件携带的数据(字符串) |
RequestId |
string? |
关联的请求 ID,无关联时为 null |
MessageId |
string |
事件帧唯一 ID |
可以创建多层继承链,每层程序集各自在 PythonScripts/ 放脚本,运行时自动合并:
SpecialWrapper : BaseWrapper : GzPythonWrapper
启动时,ScriptSources 沿继承链向上扫描:
SpecialWrapper 所在程序集的 PythonScripts/*.pyBaseWrapper 所在程序集的 PythonScripts/*.pyGzPythonWrapper 的 gz_core.py / gz_sdk.py 始终包含三份脚本最终在同一 Python 工作目录中,相互 import 完全正常。每层程序集的 csproj 都需要声明 <EmbeddedResource Include="PythonScripts\**\*.py" />。
var result = await py.CallAsync("process", new { P1 = "input" });
if (result.Success)
Console.WriteLine($"请求已提交,ID: {result.RequestId}");
else
Console.WriteLine(result.Error);
GzResult 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
Success |
bool |
Python 是否已成功接受请求 |
RequestId |
string |
本次请求的唯一码 |
Error |
string? |
失败时的错误信息 |
| 属性 | 类型 | 默认 | 说明 |
|---|---|---|---|
WrapperId |
string |
"" |
绑定 GzPythonWrapper.Id,自动订阅该实例日志 |
MaxLines |
int |
300 |
最大保留行数 |
ShowTimestamp |
bool |
true |
是否显示时间戳 |
控件无主题属性,始终跟随全局主题,调用 SuperApp.ToggleTheme() 即可,无需配置。
| 成员 | 类型 | 说明 |
|---|---|---|
Id |
string |
实例唯一 8 字符码,绑定到 GzPyConsoleCtrl.WrapperId |
Status |
string |
当前状态文本(自动维护:未启动 / 启动中 / 运行中 / 已释放) |
LastHeartbeat |
string |
最近一次心跳内容(自动更新) |
IsRunning |
bool |
Python 进程是否正在运行 |
CallAsync(method, args) |
Task<GzResult> |
调用 Python RPC 方法 |
Subscribe(eventName, handler) |
void |
订阅 Python 推送的命名事件 |
ReleaseAsync() |
Task |
断开连接,终止进程 |
| 成员 | 类型 | 说明 |
|---|---|---|
UserScriptsDirectory |
string? |
外部 Python 脚本目录路径,运行时动态挂载(默认 null 不挂载) |
LogFilePath |
string? |
Python 进程日志输出文件路径(默认 null 不写文件) |
ScriptSources |
IEnumerable<IGzScriptSource> |
脚本来源列表,默认沿继承链扫描各程序集的 PythonScripts/;可完全覆盖实现自定义加载逻辑 |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 7.23.7 | 100 | 5/22/2026 |
| 7.23.6 | 97 | 5/22/2026 |
| 7.23.5 | 93 | 5/13/2026 |
| 7.23.4 | 96 | 5/13/2026 |
| 7.23.3 | 102 | 5/13/2026 |
| 7.23.2 | 95 | 5/13/2026 |
| 7.23.1 | 91 | 5/12/2026 |
| 7.23.0 | 95 | 5/12/2026 |
| 7.21.0 | 96 | 5/12/2026 |
| 7.20.0 | 96 | 5/12/2026 |
| 7.19.1 | 100 | 5/11/2026 |
| 7.19.0 | 94 | 5/11/2026 |
| 7.18.0 | 105 | 4/30/2026 |
| 7.17.0 | 104 | 4/29/2026 |
| 7.16.2 | 106 | 4/14/2026 |
| 7.16.0 | 106 | 4/13/2026 |
| 7.15.10 | 98 | 4/13/2026 |
| 7.15.6 | 97 | 4/13/2026 |
| 7.15.5 | 99 | 4/12/2026 |
| 7.15.1 | 99 | 4/12/2026 |
docs(gotest-agent): add Profile file naming rule to engineer prompt