聊聊c#与Python以及IronPython

简单说说这个意义。做了很久的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(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(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(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(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 lst = new List(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 lst = new List(path.Count);
            lst.AddRange(path);
            lst.Add("debug");
            engine.SetSearchPaths(lst.ToArray());

 (3)

  var options = new Dictionary();

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

返回去看了看博文,差不多了,拜拜。

 

 

  

   

 

 

 

 

  

你可能感兴趣的:(c#,Python,IronPython)