C# 調用Python腳本 python腳本反調用C#方法 python腳本調用另一個腳本


今天介紹一下如何在C#側調用Python腳本,並且做一些有趣的實驗。

 

首先介紹一下今天的主角,IronPython,大名鼎鼎,想要了解的可以去它的官網看看相關的介紹,很帶勁。http://ironpython.net/

新建一個C#的控制台項目,然后使用nuget安裝這個IronPython組件

Install-Package IronPython

 

好了,開始學習吧。

首先我們需要理解,為什么會需求腳本?沒有腳本行不行?當然行啊!但是我們可以想象一下一個需求。我們從設備獲取到了一個數據,比如是 float a = 100f; 但是這個數不是最終的數,而是需要運算的,比如是要縮小10倍才是正確的數。

那么我們會  a = a / 10;  如果業務變成了會縮小N倍,這個倍數不一定,經常會調整。好了,我們就把這個倍數做成了配置項,保存在txt里,然后從txt加載倍數,然后來動態調整,這時候我們的程序已經很靈活了。

在txt里寫入 10 就是縮小10倍,寫入0.5就是放大兩倍。OK,現在業務變得更加的復雜了!我不一定是乘除法,也可能是加減法,甚至是組合運算加減乘除法。這時候你會怎么做呢?

 

傳統的方式,我還是做配置文件,把每種情況都羅列出來,1代表乘除法,2代表加減法,3代表什么什么,等等,每種情況再做配置文件,配置項不一樣嘛。這種方式當然也可以實現,只是

1. 比較麻煩,需要寫大量的配置代碼,讀寫文件的代碼。

2. 仍然適應不了未來的變化,以后可能業務又更改了,而你一開始沒有考慮到,又要改源代碼了,然后編譯,然后部署。

 

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/

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM