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/

關於變量賦值,若是有老鐵解決了,歡迎留言。

相關文章
相關標籤/搜索