Inititalize Rhino Python on csharp startup

Hi,

I am working on a Rhino 8 C# plugin that calls Python 3 methods at runtime. The reason for mixing languages is that we have an internal Python package with functionality I don’t want to replicate in C#.

The issue I’m running into is that the Python 3 language runtime is not initialized when my plugin loads. Specifically, RhinoCode.Languages.QueryLatest(new LanguageSpec("mcneel.pythonnet.python")) returns null until the Script Editor has been opened at least once in the session.

My current workaround is using:

RhinoApp.InvokeOnUiThread(() =>
RhinoApp.RunScript(“_ScriptEditor _Close”, false)
);

This is my current Test Command:

using Rhino;
using Rhino.Runtime.Code;
using Rhino.Runtime.Code.Execution;
using Rhino.Runtime.Code.Languages;
using System.IO;
using System.Reflection;

namespace Commands
{
public class PythonTestCommand : TrnBaseCommand
{
public override string EnglishName => “PythonTestCommand”;   

 protected override Rhino.Commands.Result RunCommandLogic(RhinoDoc doc)
    {
        // 1. Get Python 3 language
        var language = RhinoCode.Languages.QueryLatest(
            new LanguageSpec("mcneel.pythonnet.python")
        );
        if (language is null)
        {
            RhinoApp.WriteLine("ERROR: Python 3 language not available.");
            return Rhino.Commands.Result.Failure;
        }

        // 2. Load embedded script and append the function call
        string? pythonCode = LoadEmbeddedScript("Scripts.PythonTest.python.py");
        if (pythonCode is null)
        {
            RhinoApp.WriteLine("ERROR: Could not load embedded Python script.");
            return Rhino.Commands.Result.Failure;
        }

        double[] data = new double[] { 1.0, 2.5, 3.7, 4.2, 5.9 };
        string dataLiteral = $"[{string.Join(", ", data)}]";
        pythonCode = pythonCode + $"\nresult = run({dataLiteral})";

        // 3. Create code object
        var code = language.CreateCode(pythonCode);

        var outputStream = new MemoryStream();
        var ctx = new RunContext
        {
            OutputStream = outputStream
        };

        code.Run(ctx);

        string output = System.Text.Encoding.UTF8
            .GetString(outputStream.ToArray())
            .Trim();

        RhinoApp.WriteLine($"[PythonTest] {output}");

        return Rhino.Commands.Result.Success;
    }

    private static string? LoadEmbeddedScript(string resourceName)
    {
        var assembly = Assembly.GetExecutingAssembly();
        using var stream = assembly.GetManifestResourceStream(resourceName);
        if (stream is null) return null;
        using var reader = new StreamReader(stream);
        return reader.ReadToEnd();
    }
}
}
}

Can anybody point me into the right direction or provide ressources?

does this help:

1 Like

Thanks @Willem ,running a dummy script for me did the trick. I just added a warmup.py and let that run on OnEndDocumentInitialViewUpdate() Event

private void AddPython()
{
string tempPath = Path.Combine(Path.GetTempPath(), “MyPlugin_warmup.py”);
File.WriteAllText(tempPath, “pass\n”);

 RhinoApp.InvokeOnUiThread(() =>
     RhinoApp.RunScript($"_-ScriptEditor _R \"{tempPath}\"", false)
 );

}

My warmup.py i just:

pass

After that i am able to just run my commands and methods that use other python scripts :slight_smile: !