簡單說說這個意義。做了很久的c#,突然發現Python火了。就看看,估計這篇博文有點長,有點長,盡量包括主要的東西,還有點雜,瀏覽吧,選擇自己喜歡的看看。
先看比較。網上一堆各種比較。但是主要比較語法。我感覺這個沒有說的。Python語法就是簡單,它的設計目的就是為了簡潔。這個不管怎么比較都是Python簡單。但是寫了很久的c#,這樣反而不習慣,因為c#有很多語法糖。其實c#最近都沒有什么更新,后面再說這個。
再看性能,這個都說靜態語言占據優勢,具體我沒有自己測試過。就不多說,大家有興趣自己測試吧。
那么就是比起c#,java這些語言,Python的優勢就是簡潔小巧。先說到這里,后面再說。
接下來我們看看c#與Python的結合體IronPython。IronPython其實就是c#版本的Python的解釋器,另外也有java版本的.這個玩意是微軟支持的,但是作者是Python的原作者。
再來具體看看這個玩意的使用。可以在官網下載http://ironpython.net。也可以提供nuget直接加入。但是提醒大家的是這個玩意支持的Python3還不穩定,有的功能沒有。
具體看看使用
1.代碼中執行語句或者表達式
其實就是類似我們在Pyhon的交互下的輸入。
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
string script = "print('Hello world!')";
var sourceCode = engine.CreateScriptSourceFromString(script);
var result = sourceCode.Execute<object>(scope);
Console.WriteLine(result);
看例子,主要就是調用的方法
engine.CreateScriptSourceFromString
實現語句或者表達式的執行。
再來,看看語句的參數傳入
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
string script = "print('Hello %d' %number)";
scope.SetVariable("number", 123);
ScriptSource sourceCode = engine.CreateScriptSourceFromString(script);
var result = sourceCode.Execute<object>(scope);
Console.WriteLine(result);
看見沒有,其實就是ScriptScope 這個東東,這個就是這一次的執行玩意,通過它傳入參數的值。
因為這玩意是c#的解釋器,所以有更加高級一點的東西支持。
定義一個c#類。
public class Foo
{
public string Name { get; set; }
public DateTime Birthday { get; set; }
public string DoSth()
{
return DateTime.Now.ToString();
}
}
再來一個例子
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
string script = @"print('Hello %s' %foo.Name)
foo.DoSth()";//注意這里換行是必須的
Foo foo = new Foo()
{
Name = "阿薩德",
Birthday = new DateTime(1999,2,2)
};
scope.SetVariable("foo", foo);
ScriptSource sourceCode = engine.CreateScriptSourceFromString(script);
var result = sourceCode.Execute<object>(scope);
Console.WriteLine(result);
你會發現執行是成功的。拋開Python。.NET平台本來就是支持動態語言執行的,這就是dynamic關鍵字為什么可以有,不清楚你可以再回過頭看看dynamic。其實又回到.Net平台執行了。
這里表達式執行就說完了。
2.執行py文件
這個就是一般的Python的樣子了,繼續看例子。
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
string path = @"test.py";
Foo foo = new Foo()
{
Name = "阿薩德",
Birthday = new DateTime(1999,2,2)
};
scope.SetVariable("foo", foo);
ScriptSource sourceCode = engine.CreateScriptSourceFromFile(path);
var result = sourceCode.Execute<object>(scope);
Console.WriteLine(result);
把Doth方法移動到py文件,里面寫入上面例子的表達式,可以看效果。
這樣就介紹完了c#調用Python腳本了。
3.IronPython特性的混合編程
(1)函數調用
繼續,例子走前面
ScriptRuntime pyRuntime = Python.CreateRuntime(); //創建一下運行環境
dynamic obj= pyRuntime.UseFile("debug.py");
int num1=3, num2=4;
int sum = obj.add(num1, num2); //調用Python文件中的求和函數
注意,上面的使用方法是c#直接調用py文件的add函數,這也是一種py文件的執行,但是它的使用已經和c#混在了一起。
(2)引入.NET庫和對象
先看例子
from System import DateTime, String
formatStr = String.Format("{0} {1}", "Hello World! The current date and time is ", DateTime.Now)
print formatStr
print dir(String)
raw_input("press Enter to exit!")
這是一段Python代碼,里面有使用.NET中的String和DateTime。這段代碼可以使用前面的表達式方法或者py文件執行。這就直接使用了c#的東西。
再接着來一個,看例子
namespace CalcLib
{
public class Calc
{
public int Add(int a, int b)
{
return a + b;
}
public int Sub(int a, int b)
{
return a - b;
}
}
}
假如上面這個是開發的一個c#的CalcLib.dll,我現在需要按照Python來執行。
import clr
clr.AddReference('CalcLib')
#clr.AddReferenceToFile('CalcLib.dll')
from CalcLib import Calc
print dir(Calc)
calcObj = Calc()
print "result of 3+4 is:", calcObj.Add(3,4)
print "result of 10+2 is:", calcObj.Sub(10,2)
raw_input("press Enter to exit!")
這又是一段Python的代碼了,就可以使用了。注意,這要求IronPython能夠找到CalcLib.dll。把CalcLib.dll拷貝到項目的debug目錄或者在在使用的IronPython時,添加路徑,通過engine.SetSearchPaths設置。
好了,c#與Python的交互就聊到這里,更加復雜的就不說了。
3.接下來說說IronPython調用問題了
先貼段代碼
//ScriptRuntime pyRuntime = Python.CreateRuntime(); //創建一下運行環境
//ScriptEngine engine = Python.CreateEngine();
//engine.CreateScriptSourceFromString("print('hello!')").Execute();
//Console.ReadLine();
ScriptRuntime pyRuntime = Python.CreateRuntime(); //創建一下運行環境
ScriptEngine engine = Python.CreateEngine();
engine.SetSearchPaths(new string[] { });//設置庫的搜索
//ScriptScope obj = pyRuntime.UseFile("debug.py"); //調用一個Python文件
//obj.ImportModule("");
//engine.ImportModule("");
//pyRuntime.ExecuteFile("debug.py");
//ScriptScope runScope = pyRuntime.CreateScope();
ScriptScope engScope = engine.CreateScope();
dynamic obj= engine.ExecuteFile("debug.py",engScope);//開始調用解析(與Python文件調試過程一樣)
obj= engine.CreateScriptSourceFromFile("debug.py", Encoding.UTF8);
int num1=3, num2=4;
int sum = obj.add(num1, num2); //調用Python文件中的求和函數
//Console.Write("Sum:");
看見沒有,那一堆的調用方法,其實實現是一樣的,這就是Python的設計思想和c#的不同。Python是一個方法解決一件事情,即使它不是那么優雅,也不會擴展成多個方法,而c#則是提供多個方法解決一件事情,看起來靈活,滿足各種參數傳遞。
其實這里的真實的順序ScriptRuntime,ScriptEngine,ScriptScope,ScriptSource。具體是什么大家自己搜索。
我們調用時,無非是IronPython自動在后面默認創建了。比如直接用ScriptEngine執行py文件,則ScriptRuntime默認創建了,反過來用ScriptRuntime執行,也是默認創建了一個ScriptEngine,還是調用了ScriptEngine。按照c#一般的使用方式所以給了下面的代碼。
ScriptEngine engine = Python.CreateEngine();
//添加搜索路徑
var path=engine.GetSearchPaths();
List<string> lst = new List<string>(path.Count);
lst.AddRange(path);
lst.Add("debug");
engine.SetSearchPaths(lst.ToArray());
//
engine.ImportModule("");//標准模板
engine.ExecuteFile("debug.py");
engine.Execute("print('hell0')");
// ScriptSource scriptSource=
//engine.CreateScriptSourceFromFile("debug.py");//這里有一個編譯過程
// scriptSource.Execute();
//如果有方法調用。
dynamic rpython = engine.ExecuteFile("debug.py");
rpython.Add(3, 4);
這大概就是大家常見的過程了。另外我注釋的部分編譯過程,在引擎調用ExecuteFile方法時內部就默認創建調用了該過程。前面已經介紹了幾個類的執行過程。
4.解決問題了
模塊搜索
(1)
ScriptEngine engine = Python.CreateEngine();
engine.ImportModule("");//標准模板
(2)
//添加搜索路徑
var path=engine.GetSearchPaths();
List<string> lst = new List<string>(path.Count);
lst.AddRange(path);
lst.Add("debug");
engine.SetSearchPaths(lst.ToArray());
(3)
var options = new Dictionary<string, object>();
options["Frames"] = true;
options["FullFrames"] = true;
ScriptEngine engine = Python.CreateEngine(options);
最好的解決方法,項目定住庫的位置,然后在調用的py文件里面加入以下代碼:
import re,sys
sys.path.append("C:\Users\Administrator\Desktop\python\ironPython\WebApplication1\Lib") //這是本地調式用庫
sys.path.append("C:\ironPython\Lib")
直接把Python的問題放在Python中解決。
編輯器問題
編輯器所在主線程模式只能使用STA線程,這也是vs默認的。
這也就差不多了,最后說說vs2017開發.
在vs2017中可以開發Python.需要在vs安裝選擇Python.這樣其實配置vs2017的一些環境(可以選擇安裝Python3.6,這是vs2017集成安裝的版本)。會在項目創建中添加Python項。
另外值得注意的是,一些博文說VS安裝的Python是建立在vs安裝目錄下,但是我當前機器已經安裝了官網Python環境,所以vs創建Python默認環境就是我已經安裝好的官網Python環境,但是發現可以右鍵Python環境進行修改添加。vs2017可以執行,但是沒有編輯提示,需要安裝插件python for visual studio。
值得一說的vs2017的Python項目創建里面是2類,一類是Python應用程序,一類是IronPython應用程序,看清楚了。都是需要環境的。
好了,回到正題了,說說c#與Python了。
一直以來形成了java占據web,c#占據桌面系統開發。這是和各自的生態環境相關的,由於.NET長期閉源,被java搶占了市場,java有很多開源組件。Python由於自己的特點,占據了數據分析,人工智能方面。所以是根據各自優勢來的。
所以完整的比較是沒有意義的。另外由於.NET這種大平台(還有java)是由有關企業占用主導,所以只會關注最基礎的實現和提供庫,不像Python是由社區來引導支持的,這就造成了一種局面。Python在某一方有開源的庫支持,最后變成了標准,然后又以模塊的方式提供。但是c#就不會,只會提供最基礎的,然后專注技術優化,性能優化,新技術創新。這樣就決定了市場環境。那么Python就多了一個優勢,在某一方面有標准庫(優秀的第三方庫)來支持,而c#不會有,從定位和開發驅動就決定了。例如,c#就不可能專門提供數據分析類似Python的pandas,只會提供一般的數據處理類(例如文件讀取,包括json處理都是第三方的),這就是c#的定位,否則會很臃腫。
接着說說c#,.NET,vs2017.簡單說幾句廢話,c#是開發語言,是.NET平台支撐的一種。vs2017是開發工具,簡單說就是編輯器,只是集成了.NET平台和各種庫,這樣vs2017就支撐了很多語言開發,c#,VB,java,js,vb,F#.所以vs2017變得臃腫巨大,.NET也在支撐,也在逐步增加,所以你看看,如果再提高某個方向的庫,會變成什么樣子。值得一說的是,其實到.NET4.0以后,基本就沒有新的技術出現了,對於c#,只是提供了語法糖,編譯器自動轉換罷了,優勢是我們自己的cs文件可能小了,編譯器大了。
不多說,不然又是一堆廢話,還不少。
對於一個大學生即將就業,哪個好?根據你所在的地方,能夠讓你就業就是好的。對於一個程序員,哪個好?哥們,別比較了,你已經有一門語言在吃飯了,對於你來說,這輩子很大可能不會只用一種語言開發。對於這么熱門的數據分析和人工智能,你得學Python啊。其實語法很簡單,你只需要了解庫,到時網上查就是了。
最最后,前面雖然提到了混合編程,但是最好不要這么做。如果如例子那樣調用c#庫,既然是c#為啥不直接使用呢,還要多個Python方式,簡直無語,不知道為啥會這樣提供。所以一般情況是寫好Python文件然后調用一個入口,返回結果就好了,混合編程完全沒有必要,多次一舉。
然后是注意Python庫,官網Python實際是CPython.解釋器是c寫的,所以可以執行c代碼庫,但是IronPython是c#版本的,執行不了,而CPython為了速度,性能方面的優化,有些庫是c的,所以打算混合開發前你要注意你的庫了。還有就是前面說的IronPython現在支持2.7。3.x還不穩定,小心了。作為架構設計者,這些要注意了,最好不要混合編程,這種思路就是給自己挖坑,不到不得已的時候堅決不要有混合編程,需要填很多坑。
最后再為大家提供一個思路吧。把項目變成分布式服務。一端用c#,一端用CPython。用網絡進行溝通。其實我們要用IronPython,就是因為Python有很多現成的庫(某個方向,某個領域,例如前面提到的數據分析),一旦沒有了,其實就沒有必要了。作為設計者一定要平衡,或者用c#實現一個類似的庫。這個投入就大了,就看老板的態度了,還要測試,最后還要和Python比較誰好,但願隨着c#開源,net core跨平台,有沒有優秀的第三方庫來支持,就😩不用考慮用IronPython了。
提一下,Python多線程不能提高速度,始終是一個線程在一刻執行,已經提供了代碼優化(其實是多進程的)。
就不繼續擴展了,還有些廢話,就不說了,原本還打算聊聊混合編程的問題,到此打住,大家多交流吧。
完成這篇博文,居然花了好幾個小時,奇怪了。邊用vs2017測試。同時測試Python環境。至於JPython我就不聊了,這畢竟不是我主業。
vs2017中開發Python,推薦一篇博文設置環境。https://blog.csdn.net/manjiang8743/article/details/79517135
返回去看了看博文,差不多了,拜拜。