BotSharp/src/Plugins/BotSharp.Plugin.PythonInterpreter/Services/PyInterpretService.cs

130 lines
4.1 KiB
C#
Raw Normal View History

2025-10-08 02:57:08 +00:00
using BotSharp.Core.CodeInterpreter;
2025-09-30 17:10:02 +00:00
using Microsoft.Extensions.Logging;
using Python.Runtime;
2025-10-08 20:25:53 +00:00
using System.Threading;
2025-09-30 17:10:02 +00:00
using System.Threading.Tasks;
namespace BotSharp.Plugin.PythonInterpreter.Services;
public class PyInterpretService : ICodeInterpretService
{
private readonly IServiceProvider _services;
private readonly ILogger<PyInterpretService> _logger;
2025-10-08 02:57:08 +00:00
private readonly CodeScriptExecutor _executor;
2025-09-30 17:10:02 +00:00
public PyInterpretService(
IServiceProvider services,
2025-10-08 02:57:08 +00:00
ILogger<PyInterpretService> logger,
CodeScriptExecutor executor)
2025-09-30 17:10:02 +00:00
{
_services = services;
_logger = logger;
2025-10-08 02:57:08 +00:00
_executor = executor;
2025-09-30 17:10:02 +00:00
}
2025-10-02 00:58:28 +00:00
public string Provider => "botsharp-py-interpreter";
2025-09-30 17:10:02 +00:00
2025-10-01 01:45:32 +00:00
public async Task<CodeInterpretResult> RunCode(string codeScript, CodeInterpretOptions? options = null)
2025-10-08 02:57:08 +00:00
{
2025-10-08 20:25:53 +00:00
if (options?.UseMutex == true)
{
return await _executor.Execute(async () =>
{
return InnerRunCode(codeScript, options);
}, cancellationToken: options?.CancellationToken ?? CancellationToken.None);
}
2025-10-08 02:57:08 +00:00
return InnerRunCode(codeScript, options);
}
private CodeInterpretResult InnerRunCode(string codeScript, CodeInterpretOptions? options = null)
2025-09-30 17:10:02 +00:00
{
try
{
2025-10-08 02:57:08 +00:00
return CoreRun(codeScript, options);
}
catch (Exception ex)
{
var errorMsg = $"Error when executing inner python code in {nameof(PyInterpretService)}: {Provider}.";
_logger.LogError(ex, errorMsg);
return new CodeInterpretResult
2025-09-30 17:10:02 +00:00
{
2025-10-08 02:57:08 +00:00
Success = false,
ErrorMsg = errorMsg
};
}
}
2025-09-30 17:10:02 +00:00
2025-10-08 02:57:08 +00:00
private CodeInterpretResult CoreRun(string codeScript, CodeInterpretOptions? options = null)
{
using (Py.GIL())
{
// Import necessary Python modules
dynamic sys = Py.Import("sys");
dynamic io = Py.Import("io");
try
{
2025-09-30 17:10:02 +00:00
// Redirect standard output/error to capture it
dynamic stringIO = io.StringIO();
sys.stdout = stringIO;
sys.stderr = stringIO;
// Set global items
using var globals = new PyDict();
2025-09-30 20:26:32 +00:00
if (codeScript.Contains("__main__") == true)
2025-09-30 17:10:02 +00:00
{
globals.SetItem("__name__", new PyString("__main__"));
}
// Set arguments
2025-10-01 15:21:58 +00:00
var list = new PyList();
2025-10-01 01:45:32 +00:00
if (options?.Arguments?.Any() == true)
2025-09-30 17:10:02 +00:00
{
2025-10-08 20:12:00 +00:00
list.Append(new PyString(options?.ScriptName.IfNullOrEmptyAs("script.py")));
2025-09-30 17:10:02 +00:00
2025-10-01 01:45:32 +00:00
foreach (var arg in options.Arguments)
2025-09-30 17:10:02 +00:00
{
2025-09-30 20:03:06 +00:00
if (!string.IsNullOrWhiteSpace(arg.Key) && !string.IsNullOrWhiteSpace(arg.Value))
{
list.Append(new PyString($"--{arg.Key}"));
list.Append(new PyString($"{arg.Value}"));
}
2025-09-30 17:10:02 +00:00
}
}
2025-10-01 15:21:58 +00:00
sys.argv = list;
2025-09-30 17:10:02 +00:00
// Execute Python script
2025-09-30 20:26:32 +00:00
PythonEngine.Exec(codeScript, globals);
2025-09-30 17:10:02 +00:00
// Get result
2025-10-01 01:45:32 +00:00
var result = stringIO.getvalue()?.ToString() as string;
2025-09-30 17:10:02 +00:00
return new CodeInterpretResult
{
2025-10-01 01:45:32 +00:00
Result = result?.TrimEnd('\r', '\n'),
2025-09-30 17:10:02 +00:00
Success = true
};
}
2025-10-08 02:57:08 +00:00
catch (Exception ex)
{
var errorMsg = $"Error when executing core python code in {nameof(PyInterpretService)}: {Provider}. {ex.Message}";
_logger.LogError(ex, errorMsg);
2025-09-30 17:10:02 +00:00
2025-10-08 02:57:08 +00:00
return new CodeInterpretResult
{
Success = false,
ErrorMsg = errorMsg
};
}
finally
2025-09-30 17:10:02 +00:00
{
2025-10-08 02:57:08 +00:00
// Restore the original stdout/stderr/argv
sys.stdout = sys.__stdout__;
sys.stderr = sys.__stderr__;
sys.argv = new PyList();
}
2025-09-30 17:10:02 +00:00
}
}
}