IronPython使用

最近一个项目,需要在WPF的页面中实现Python的调用,不用很复杂的Python模块,只使用原生的Python完成一些判断逻辑下的下单即可。

之前也做过类似的项目,但是那是在大神的领导的框架下实现的,为了能兼容Python的第三方模块的调用,使用了CPython,这个实现就很复杂了,具体的原理是在C++,Python和C#三个对象之间做了转换,最终是可以实现了,过程很复杂,需要修改Cpython的源码,这次没有大神的参与,需要自己实现,我选择了简单的IronPython,目前看是可以满足需求的。

使用IronPython就比较简单了,IronPython和C#之间天然就是可以互相调用的。查了一些使用方法之后,开始按照自己的需求实现,主要实现以下几种调用方式,符合我的使用需求,在满足一定的条件之后实现下单。

1,最简单的使用方式,在C#中执行Python的方法

Python脚本

@"results = list()

def GetResults():
    results.append('start')
    results.append('start')
    return  results

C#后台代码
            ScriptEngine engine = Python.CreateEngine();
            ScriptScope scope = engine.CreateScope();
            var sourceCode = engine.CreateScriptSourceFromString(formulaEditor.Text);
            sourceCode.Execute<object>(scope);

            1,直接使用results的列表
            var res = scope.GetVariable("results");
            IronPython.Runtime.List list = res as IronPython.Runtime.List;

            2,通过执行GetResults方法获取到results的结果
            var test = scope.GetVariable<Func<object>>("GetResults");
            object res = test();
            IronPython.Runtime.List list = res as IronPython.Runtime.List;

以上是两种获得返回值的方法,一种是调用方法,一中是直接使用List。

2,要在C#的窗体种执行完Python脚本,并且把结果实时输出到窗体中,我最后选择了事件的调用方式传递 

Python代码

def SetResults():
    Broadcast('Test')
    Broadcast('Start')
    Broadcast('Start')

C#代码

 private void EventTriggerWindow_Broadcast(string a)
        {
            Dispatcher.Invoke(() => { OutResults.Add(a); });
        }

        public delegate void BroadcastEventHander(string a);
        public event BroadcastEventHander Broadcast;

           ScriptEngine engine = Python.CreateEngine();
            ScriptScope scope = engine.CreateScope();
            var sourceCode = engine.CreateScriptSourceFromString(formulaEditor.Text);
            
            scope.SetVariable("Broadcast", Broadcast);
            sourceCode.Execute<object>(scope);
            var test = scope.GetVariable<Func<object>>("SetResults");
            Task.Run(() => { test(); });

通过事件Broadcast在Python中实时输入运行结果,现实到C#的窗体控件上

3,想要实现在C#中定义事件,然后在Python中触发事件,具体代码如下

Python脚本

def SendOrder(stkid):
    Broadcast(stkid)

def SetResults():
    Broadcast('Start')
    QuotationSource.Broadcast+=SendOrder
    QuotationSource.SubScribe('1000001')
    Broadcast('End')

C#代码

定义了一个类

 public class QuotationSource
    {
        public string StkId { get; set; }

        public QuotationSource()
        { }
        public void SubScribe(string stkId)
        {
            this.StkId = stkId;
        }

        public void OnTick()
        {
            if (Broadcast != null)
                Broadcast(StkId);
        }
        public delegate void BroadcastEventHander(string args);
        public event BroadcastEventHander Broadcast;
    }

点击按钮的时候触发事件

 private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            quotationSource.OnTick();
        }

ScriptEngine engine = Python.CreateEngine();
            ScriptScope scope = engine.CreateScope();
            var sourceCode = engine.CreateScriptSourceFromString(formulaEditor.Text);
            
            scope.SetVariable("QuotationSource", quotationSource);
            scope.SetVariable("Broadcast", Broadcast);
            sourceCode.Execute<object>(scope);
            var test = scope.GetVariable<Func<object>>("SetResults");
            Task.Run(() => { test(); });

这样就实现了Python中执行C#的事件触发

整体项目也会上传,代码写的比较乱,因为是个Demo我也没有整理

IronPython和C#交互-C#文档类资源-CSDN下载

上一篇:Hudi的更新机制


下一篇:How Tomcat Works_9_12