C# 调用Python脚本 python脚本反调用C#方法 python脚本调用另外一个脚本

今天介绍一下如何在C#侧调用Python脚本,而且作一些有趣的实验。html

 

首先介绍一下今天的主角,IronPython,大名鼎鼎,想要了解的能够去它的官网看看相关的介绍,很带劲。http://ironpython.net/python

新建一个C#的控制台项目,而后使用nuget安装这个IronPython组件数组

Install-Package IronPython

 

好了,开始学习吧。网络

首先咱们须要理解,为何会需求脚本?没有脚本行不行?固然行啊!可是咱们能够想象一下一个需求。咱们从设备获取到了一个数据,好比是 float a = 100f; 可是这个数不是最终的数,而是须要运算的,好比是要缩小10倍才是正确的数。学习

那么咱们会  a = a / 10;  若是业务变成了会缩小N倍,这个倍数不必定,常常会调整。好了,咱们就把这个倍数作成了配置项,保存在txt里,而后从txt加载倍数,而后来动态调整,这时候咱们的程序已经很灵活了。.net

在txt里写入 10 就是缩小10倍,写入0.5就是放大两倍。OK,如今业务变得更加的复杂了!我不必定是乘除法,也多是加减法,甚至是组合运算加减乘除法。这时候你会怎么作呢?线程

 

传统的方式,我仍是作配置文件,把每种状况都罗列出来,1表明乘除法,2表明加减法,3表明什么什么,等等,每种状况再作配置文件,配置项不同嘛。这种方式固然也能够实现,只是debug

1. 比较麻烦,须要写大量的配置代码,读写文件的代码。3d

2. 仍然适应不了将来的变化,之后可能业务又更改了,而你一开始没有考虑到,又要改源代码了,而后编译,而后部署。code

 

ok,如今能够尝试一种全新的技术(其实脚本技术不算新),这里的新技术主要是对于刚接触的人来讲。

咱们针对上面的需求进行实现。

 

 

 

咱们如今程序的debug目录下,新建一个hsl.py文件,方便咱们的调用,而后咱们使用VS CODE 进行编辑这个文件,关于如何安装python及配置环境啥的,能够参考下面的文章:

https://www.cnblogs.com/dathlin/p/12142663.html

好了,如今开始编辑了,咱们须要定义一个转换的方法,以下所示

 

 

 

而后咱们在C#里写下面的代码

static void Main( string[] args )
        {
            float value = 123f; // 模拟咱们获取到的数据


            Microsoft.Scripting.Hosting.ScriptEngine engine = IronPython.Hosting.Python.CreateEngine( );
            dynamic script = engine.ExecuteFile( "hsl.py" );

            float result = script.GetActulValue( value );

            Console.WriteLine( $"Value Old:{value}  New Value:{result}" );
            Console.ReadLine( );
        }

  

咱们运行起来看看,看看会输出什么?

 

 

 

这时候应该发出震撼的声音,我去!竟然真的能够,咱们在看看修改下python脚本的代码

 

 

 看看结果

 

 

 

 上述的例子太简单了,咱们来看看更高级的数学方法

 

 

 咱们改的更高级一点了。这个数能够算出啥。我也不知道了。因此咱们看看,这玩意能输出什么?

 

 

 emmmmm.....报错了,python的运算以后结果变成了double类型,应该是math处理方法的缘由,因此咱们的C#代码要万无一失的话,稍微改改

 

 

 

好了,看来咱们能够用一些python本身的库相关的代码,均可以执行。接下来咱们看看下面的py代码

 

 

 咱们看看这个效果

 

 

 这么看来也是没有任何问题的。

这样的话,就能够完成一些很高级的自定义的脚本操做了。

 

 

 

你觉得到这里就结束了?接下来才是给力的部分。上述已经实现了文章开篇提出的需求了,接下来咱们看看一个更高级的需求。

在C#里有五个方法。A,B,C,D,E表明了业务的五个部分,咱们的主体业务是分别调用这五个方法,进行排列组合,甚至,有的不执行,或是执行屡次。若是须要这种业务应该怎么办呢?

一样是脚本是最合适,咱们须要在python里调用C#的这五个方法。

那么第一步就是定义这五个方法

public static void A( )
        {
            Console.WriteLine( "Method A Called" );
        }

        public static void B( )
        {
            Console.WriteLine( "Method B Called" );
        }

        public static void C( )
        {
            Console.WriteLine( "Method C Called" );
        }

        public static void D( )
        {
            Console.WriteLine( "Method D Called" );
        }

        public static void E( )
        {
            Console.WriteLine( "Method E Called" );
        }

  很简单,只要被调用一次,就会打印出记录,方便咱们跟踪。

static void Main( string[] args )
        {
            Microsoft.Scripting.Hosting.ScriptEngine engine = IronPython.Hosting.Python.CreateEngine( );
            Microsoft.Scripting.Hosting.ScriptScope scope = engine.CreateScope( );
            scope.SetVariable( "A", new Action( A ) );
            scope.SetVariable( "B", new Action( B ) );
            scope.SetVariable( "C", new Action( C ) );
            scope.SetVariable( "D", new Action( D ) );
            scope.SetVariable( "E", new Action( E ) );
            engine.ExecuteFile( "hsl.py", scope );

            Action business = scope.GetVariable<Action>( "MainBusiness" );
            business( );  // 调用主业务现实

            Console.ReadLine( );
        }

  这里咱们不用C#的动态语法来执行脚本了,咱们经过获取委托的方式,固然了,咱们先把这五个方法,传进python里面去,就能够调用了,python的代码以下,须要注意的是,方法名和上面的要同样

 

 

ok,很简单的,就是顺序调用一下而已,好了,咱们如今看看输出

 

 

我去,真的能够啊,牛逼,不由再次感叹下,来来来,咱们的脚本写的更加复杂点。

 

 咱们还加入的循环体,来来来,继续看看效果。

 

 

我去,牛逼!!!

再来看看变量呢?

 

 

咱们新增长一个count变量,而后传入到python脚本,看看python能不能获取到

 

 而后咱们运行C#侧的代码

 

 

能够获取到,咱们如今来更改值看看

 

 就是简单的修改一个值。

 

 

 发现没有更新,那么能够推断,传入Python的值变量,只是数据的副本,那么咱们应该传入引用变量

 

 

 咱们定义了一个匿名类型,若是这部分不清楚,就能够去补补C#的知识了。

 

 好了,咱们再运行看看

 

 额,,,,发生异常了。这里暂时尚未想明白,不过暂时的解决能够经过返回值来解决,咱们让业务方法返回数据,进行更改。若是有网友知道怎么解决,很是感谢。

 

 

 

 

 运行看效果。

 

 

 

OK,最后咱们来看看,若是我还有一个py的脚本文件。实现另外一个方法,F()

 

 

我须要在上面的脚本里调用这个方法。

 

 咱们同时加载第二个文件,而后更改第一个py文件的代码

 

 

而后咱们看运行效果。

 

 

ok,能够,很是好,剩下的细节就要结合实际开发了。接下来看一个例子:

咱们在项目里面安装 HslCommuncation

 

 

咱们在C#的代码里生成一个链接西门子的网络对象类。而且把这个类传递给Python,那么代码以下所示:

static void Main( string[] args )
        {
            var data = new Good (){ Name = "BooK", Price = 10 };
            Microsoft.Scripting.Hosting.ScriptEngine engine = IronPython.Hosting.Python.CreateEngine( );
            Microsoft.Scripting.Hosting.ScriptScope scope = engine.CreateScope( );
            scope.SetVariable( "Good", data );
            scope.SetVariable( "A", new Action( A ) );
            scope.SetVariable( "B", new Action( B ) );
            scope.SetVariable( "C", new Action( C ) );
            scope.SetVariable( "D", new Action( D ) );
            scope.SetVariable( "E", new Action( E ) );

            HslCommunication.Profinet.Siemens.SiemensS7Net siemens =
                new HslCommunication.Profinet.Siemens.SiemensS7Net(
                    HslCommunication.Profinet.Siemens.SiemensPLCS.S1200, "192.168.8.12" );
            siemens.SetPersistentConnection( );
            scope.SetVariable( "siemens", siemens );

            engine.ExecuteFile( "hsl.py", scope );
            engine.ExecuteFile( "hsl2.py", scope );

            Func<int> business = scope.GetVariable<Func<int>>( "MainBusiness" );
            data.Price = Convert.ToInt32(business( ));  // 调用主业务现实

            Console.WriteLine( data.Price.ToString( ) );
            siemens.ConnectClose( );
            Console.ReadLine( );
        }

  

而后在python里读取西门子的数据信息。而后打印出来

 

 ok,那么咱们来执行

 

 能够,很是给力。

 

咱们再来看看写入操做。

 

 读出来是0,应该是写入的类型不对,那么咱们须要写入的是short类型,应该怎么操做呢?

 

 这样就能够读取到咱们须要的数据了。若是咱们写入的是数组呢?

 

咱们天然而然想到:

 

 结果报下面的错误。

 

 意思就是两个重载的方法不知道选哪一个,好了,问题知道了,咱们来修复下这个内容

 

 

到这里成功写入,咱们也拿到了本身的数据。

 

若是我须要使用 C#的类,这个类是我本身建立的话。

好比说这里的OperateResult

 

 若是想使用线程的技术,可使用C#的线程技术

from System.Threading import Thread, ThreadStart

  

def ThreadCheck():
    count = 0
    while True:
        count = count + 1
        time.sleep(1)
        logNet.WriteDebug('线程检测:'+ str(count))
        if count > 10:
            break

def SendMesCmdToPlc(cmd):
    Thread(ThreadStart(ThreadCheck)).Start()

 

就能够启动线程的检测

 

更详细的英文版教程以下:

https://ironpython.net/documentation/dotnet/

关于变量赋值,若是有老铁解决了,欢迎留言。

相关文章
相关标签/搜索