使用IronPython把Python脚本集成到.NET程序中的教程


Posted in Python onMarch 31, 2015

从两个优秀的世界各取所需,更高效的复用代码。想想就醉了,.NET和python融合了。“懒惰”的程序员们,还等什么?

Jesse Smith为您展示如何两个语言来服务同一个.NET程序。你能集两家所长:Python和.NET一起工作,提供可重用的代码功能而不需要你为了一个环境重写代码库。

通过使用IronPython 运行时库,你可以让Python脚本运行在你的.NET程序中。本文向你展示如何使用一个.NET程序中的python脚本获取并展示用户反馈。

如果你曾经有在一个.NET程序中运行Python脚本的需求,整合两者最好的办法是使用IronPython。我有过这样的需求。我曾经效力的一个组织需要扩展一个已经存在于一个.NET地图程序中的工具集。我们的目的是利用另一个工具集中现有的Python代码来扩展这个已有的工具集,前者还不是后者的一部分。在做了一番研究之后,我决定使用IronPython,事情进展很顺利。

本文基于上述项目的经验,我会还原当时的场景,对你所处的情境也同样适用。

对于这个我们所期望的解决方案,首先要面对的挑战是从将要运行在.NET程序中的那个Python脚本获取输出,然后使用一个.NET程序的对话框把这个输出展示给用户。让我感到吃惊的是,这么做比预想的还要简单,你同样也能学到如何去做同样的事情。整个过程相对比较简单,我们将在下面的章节中进行概述。
在.NET程序中嵌入Python脚本

在这个例子中,我向你展示如何在一个Windows桌面程序中嵌入Python脚本。目的是在一个已有的程序中添加一个新的工具按钮。点击按钮后,程序会弹出一个对话框,显示一个嵌入在对话框代码中的Python脚本的运行结果。

为了给这个例子铺垫更多的前因后果,我们这个应用程序是一个桌面地图软件,可以让用户创建他们自己的地图。这个新的工具允许用户解析和标准化他们地图上的地址点。

标准化一个地址,就意味着要确保这个地址有一个街道名,前缀或后缀,房屋或建筑编号,以及连接该街道的上一条街道和下一条街道。每一个地址段必须遵循US邮局邮编地址标准指导。

假设已有一个Python脚本已经可以做到这些;它就是例子中执行解析的脚本。Python脚本将会通过当前对话框在屏幕上输出或闪现这个正在解析的地址,我们可以通过选择地址解析工具来触发对话框(我不想说的太细,仅仅解释到这里。)

代码并不重要,重要的是知道如何嵌入脚本和如何定向脚本的输出到对话框,作为程序的一部分显示在屏幕上。这一过程像下面这样进行:

  •     用户启动地图程序并打开一个自定义地图。
  •     用户从屏幕上方的已有的工具集中选择一个新的地址标准化工具。
  •     弹出一个带有可以启动地址标准化进程的启动按钮的地址标准化对话框
  •     一个文本框显示当前正在被解析的地址。这些文本框很快消失,地址在用户眼前一闪而过,表示过程启动并且正在解析。
  •     出现一个表示整个过程结束的信息,使用了第4步中同样的文本框。

确定源代码和项目

首先要做的事情是确定脚本应该嵌入到应用程序源代码的什么位置。在我们的例子/情境下,这个位置应该是添加到包含工具集项目中的新的对话框。这个对话框会被一个已经存在的用于处理工具栏点击事件的方法所触发

当我们确定了需要包含源代码的项目后,就需要引用IronPython 库。

如果你使用Visual Studio作为编辑器的话,最简单的方法是使用Nuget Package Manager来添加IronPython库到项目中。你可以搜索”IronPython”,然后运行时库就可以在包管理工具中选择了。
嵌入脚本

接下来做的才是真正嵌入脚本。你首先要用脚本引擎(scripting engine)来设置一个Python脚本引擎实例。在添加脚本前,你同样可以设置任何你的脚本所需的特殊的路径。

ScriptEngine pyEngine = Python.CreateEngine();
pyEngine.Runtime.IO.RedirectToConsole();
var paths = pyEngine.GetSearchPaths();
paths.Add(@"C:Python27Lib");
paths.Add(@"C:Python27Libsite-packages");
pyEngine.SetSearchPaths(paths);

第二行告诉.NET框架Python引擎的运行时库会将输出重定向到控制台。然而,这并不是重定向到我们为这个应用添加的新的工具所需的对话框中。(下面的代码会做这个工作)

但是,首先我们需要通过一个简单的字符串变量来添加脚本。你需要改变你的脚本中的引号来配合字符串的引号工作。

一个简单的方法是把你脚本中的所有双引号变成单引号。嵌入脚本的语法如下:

string thescript =
  @"
  (此处为实际脚本内容)
  ";

你可能需要处理一些格式问题,但是缩进必须一致。在脚本字符串解析一个有效的字符串后,是时候添加输出重定向代码让脚本的输出显示在工具的对话框窗口中了:

Console.SetOut(TextWriter.Synchronized(new TextBoxWriter(statusText)));
    pyEngine.Execute(thescript);
    this.AllDone(FINISHED);
   }
   catch (Exception ex)
   {
    this.AllDone(ex.InnerException.StackTrace);
   }
  }
  public void AllDone(string message)
  {
   buttonStart.Enabled = true;
   this.statusLabel.Text = message;
  }

在上面这段代码中,我们设置了一个新的TextWriter,它接受一个TextBoxWriter类型的参数,这使得我们可以把脚本的输出重新写到一个文本框中。TextBoxWriter类型的代码如下:
 

public class TextBoxWriter : TextWriter
  {
   private TextBox _textBox;
   public TextBoxWriter(TextBox textbox)
   {
    _textBox = textbox;
   }
   public override void Write(char value)
   {
    base.Write(value);
    // When character data is written, append it to the text box.
    _textBox.AppendText(value.ToString());
   }
   public override System.Text.Encoding Encoding
   {
    get { return System.Text.Encoding.UTF8; }
   }
  }
 }

传入TextBoxWriter类型的statusText属性是我们的文本框,它会出现在对话框中,显示脚本的输出。我们的Python脚本中的每一个输出语句都会被重定向到这个文本框。
结论

在本文中,你学会了如何把Python脚本集成到一个.NET程序中,并且把Python的脚本文件输出到一个.NET对话框。这种无缝衔接,用户是不会感觉到的,他们并不知道实际上是Python在处理后台的一些工作。

在很多场合下,集成两种语言是很有用的。我分享了的这一情景,为我的处境提供了很好的解决方案。你可以按照类似的步骤,用同样的方法把它应用在很多场合。

我建议你去建立一个自己的简单范例,甚至使用Python脚本文件把Python代码直接加入到.NET应用中,你确实可以这样做。当然你并不需要直接把脚本嵌入在.NET源代码中,但对我来说这样做最方便。

Python 相关文章推荐
python的几种开发工具介绍
Mar 07 Python
python类型强制转换long to int的代码
Feb 10 Python
python登录豆瓣并发帖的方法
Jul 08 Python
Python3.4实现从HTTP代理网站批量获取代理并筛选的方法示例
Sep 26 Python
python列表的增删改查实例代码
Jan 30 Python
Python中str.join()简单用法示例
Mar 20 Python
Python字典推导式将cookie字符串转化为字典解析
Aug 10 Python
简单易懂Pytorch实战实例VGG深度网络
Aug 27 Python
Python爬虫实现使用beautifulSoup4爬取名言网功能案例
Sep 15 Python
python对验证码降噪的实现示例代码
Nov 12 Python
基于SpringBoot构造器注入循环依赖及解决方式
Apr 26 Python
如何理解python接口自动化之logging日志模块
Jun 15 Python
提升Python程序运行效率的6个方法
Mar 31 #Python
用Python从零实现贝叶斯分类器的机器学习的教程
Mar 31 #Python
利用Python的Flask框架来构建一个简单的数字商品支付解决方案
Mar 31 #Python
用Python进行基础的函数式编程的教程
Mar 31 #Python
python使用多线程不断刷新网页的方法
Mar 31 #Python
Python新手实现2048小游戏
Mar 31 #Python
举例介绍Python中的25个隐藏特性
Mar 30 #Python
You might like
PHPMailer邮件发送的实现代码
2013/05/04 PHP
destoon实现调用当前栏目分类及子分类和三级分类的方法
2014/08/21 PHP
php中explode函数用法分析
2014/11/15 PHP
php+ajax实时输入自动搜索匹配的方法
2014/12/26 PHP
修改yii2.0用户登录使用的user表为其它的表实现方法(推荐)
2017/08/01 PHP
PHP中cookie知识点学习
2018/05/06 PHP
js left,right,mid函数
2008/06/10 Javascript
JQuery 无废话系列教程(二) jquery实战篇上
2009/06/23 Javascript
Extjs学习过程中新手容易碰到的低级错误积累
2010/02/11 Javascript
高性能WEB开发 flush让页面分块,逐步呈现 flush让页面分块,逐步呈现
2010/06/19 Javascript
jquery提交form表单简单示例分享
2014/03/03 Javascript
jquery限定文本框只能输入数字(整数和小数)
2016/01/08 Javascript
jQuery实现控制文字内容溢出用省略号(…)表示的方法
2016/02/26 Javascript
基于BootStrap Metronic开发框架经验小结【四】Bootstrap图标的提取和利用
2016/05/12 Javascript
Angular的MVC和作用域
2016/12/26 Javascript
Layui table 组件的使用之初始化加载数据、数据刷新表格、传参数
2017/09/11 Javascript
angular4自定义组件详解
2017/09/28 Javascript
浅谈webpack下的AOP式无侵入注入
2017/11/12 Javascript
js如何找出字符串中的最长回文串
2018/06/04 Javascript
微信小程序 高德地图路线规划实现过程详解
2019/08/05 Javascript
vue中组件通信的八种方式(值得收藏!)
2019/08/09 Javascript
js 下拉菜单点击旁边收起实现(踩坑记)
2019/09/29 Javascript
vue双向绑定数据限制长度的方法
2019/11/04 Javascript
JS性能优化实现方法及优点进行
2020/08/30 Javascript
Python Sleep休眠函数使用简单实例
2015/02/02 Python
python中安装模块包版本冲突问题的解决
2017/05/02 Python
Python3 加密(hashlib和hmac)模块的实现
2017/11/23 Python
python GUI库图形界面开发之PyQt5状态栏控件QStatusBar详细使用方法实例
2020/02/28 Python
Html5 canvas画图白板踩坑
2020/06/01 HTML / CSS
巴黎卡诗美国官方网站:始于1964年的头发头皮护理专家
2017/07/10 全球购物
阿拉伯书店:Jamalon
2019/07/24 全球购物
给排水专业应届生求职信
2013/10/12 职场文书
入党自我评价范文
2014/02/02 职场文书
PyQt5 QThread倒计时功能的实现代码
2021/04/02 Python
CSS基础详解
2021/10/16 HTML / CSS
Python中的tkinter库简单案例详解
2022/01/22 Python