当前位置: 移动技术网 > IT编程>脚本编程>Python > IronPython初体验

IronPython初体验

2018年11月03日  | 移动技术网IT编程  | 我要评论

云推seo,飞车图标,黄灿盛现任女友曝光

介绍

在 c# 程序中嵌入 ironpython 得到了很好的支持。在本教程中,我们将展示如何完成这个项目。
首先,我们将展示两个非常基本的例子,说明如何执行一个不导入任何模块的非常简单的脚本。然后,再展示如何执行使用模块的脚本。

在 c# 中执行 python

第一个例子

我们来创建一个执行python脚本的 c# 应用​​程序的简单例子。我们使用 visual studio 2017 c# 控制台应用程序模板创建一个新项目。我们称之为pythonscriptexecution1。完整的例子可以从我们的github仓库获得:ironpythontutorials / csharpintegration / pythonscriptexecution1
项目创建完成后,我们使用 nuget 包管理器添加 ironpython 包,将其安装到当前项目中。这会将以下程序集添加到项目中:

  • ironpython
  • ironpython.model
  • ironpython.sqlite
  • ironpython.wpf
  • microsoft.dynamic
  • microsoft.scripting
  • microsoft.scripting.aspnet
  • microsoft.scripting.metadata

对于第一个例子,我们调用一个 python 脚本,它将简单地打印出 “hello world!”。在控制台上。为了保持它尽可能简单,我们只需将 python 代码硬编码到一个字符串中,然后使用 createscriptsourcefromstring 从中创建 microsoft.scripting.hosting.scriptsource 实例。正如你所看到的,这很容易做,只需要3行代码。

static void main(string[] args)
{
    var pythonengin = ironpython.hosting.python.createengine();
    var pythonscripts = pythonengin.createscriptsourcefromstring("print'hello world'");
    pythonscripts.execute();
}

控制台输出

hello world

如果你想了解更多关于在幕后发生的事情,你可以看看

第二个例子

第二个例子与第一个例子几乎相同,但是我们将使用 createscriptsourcefromfile 函数从文件中加载脚本,而不是将其硬编码到一个字符串中。由于我们将脚本放在与 program.cs 文件相同的目录中,我们需要当从 visual studio 执行程序时,会出现两个目录。这就是为什么我们脚本的路径是..  ..  helloworld.py。您当然可以将脚本放在与可执行文件相同的目录中。代码如下所示。执行程序时,输出当然与前面的示例相同。
完整的例子可以从我们的github仓库获得:ironpythontutorials/csharpintegration/pythonscriptexecution2

print('hello world')
static void main(string[] args)
{
    var pythonengin = ironpython.hosting.python.createengine();
    var pythonscripts = pythonengin.createscriptsourcefromfile("..\\.\\helloworld.py"));
    pythonscripts.execute();
    console.readkey();
}

搜索路径

通常,python 脚本将依赖于某个模块,或者是一个自定义模块或 python 标准库中的模块。我们将展示如何使用标准库,但是考虑到大量的模块,我们将从一个更基本的例子开始。
处理模块的唯一困难是设置引擎将查找模块的路径列表。该scriptengine的类提供了一个函数来检索的搜索路径当前列表:getsearchpaths,另一个设置列表:setsearchpaths。setsearchpaths 替换现有的列表,所以如果你想添加一个搜索路径,你将需要首先获取当前列表,添加新的路径,然后将更新的列表传递给 setsearchpaths 函数。
我们来举例说明一个简单的例子。我们修改之前的的一个示例,以便在 helloworld.py 导入另一个名为 helloworldmodule.py 的模块。我们把这两个文件放在与program.cs相同的目录下。这两个文件的来源如下所示。
完整的例子可以从我们的github仓库获得:ironpythontutorials/csharpintegration/pythonscriptexecution3

helloworldmodule.py

def printhelloworld():
    print("hello world")

helloworld.py

import helloworldmodule

helloworldmodule.printhelloworld()
static void main(string[] args)
{
    var pythonengin = ironpython.hosting.python.createengine();
    console.writeline("search paths:");
    var searchpaths = pythonengin.getsearchpaths();
    foreach (var item in searchpaths)
    {
        console.writeline(item);
    }
    console.writeline();
    searchpaths.add("..\\..");
    pythonengin.setsearchpaths(searchpaths);

    var pythonscript = pythonengin.createscriptsourcefromfile("..\\..\\helloworld.py");
    pythonscript.execute();
}

显然,这是一个稍微做作的例子,因为你通常会把脚本放在一个更合理的位置,但是你应该明白这个想法。
如果一切正常,你应该得到以下输出。

search paths:
.
c:\users\hippiezhou\documents\projects\ironpythontutorials\03_pythonscriptexecution3\bin\debug\lib
c:\users\hippiezhou\documents\projects\ironpythontutorials\03_pythonscriptexecution3\bin\debug\dlls

hello world

但是,如果由于某种原因无法找到一个模块,你会得到下面的异常抛出。

unhandled exception: ironpython.runtime.exceptions.importexception: no module na
med os
   at microsoft.scripting.runtime.lightexceptions.checkandthrow(object value)
   at microsoft.scripting.interpreter.funccallinstruction`2.run(interpretedframe
 frame)
   at microsoft.scripting.interpreter.interpreter.run(interpretedframe frame)
   at microsoft.scripting.interpreter.lightlambda.run1[t0,tret](t0 arg0)
   at ironpython.compiler.runtimescriptcode.invoketarget(scope scope)
   at ironpython.compiler.runtimescriptcode.run()
   at microsoft.scripting.hosting.scriptsource.execute()
   at pythonscriptexecution3.program.main(string[] args) in c:\p4client2\tutoria
ls\development\ironpython\examples\csharpintegration\pythonscriptexecution3\pyth
onscriptexecution3\program.cs:line 16

让我们仔细看一下搜索路径的初始列表。
默认情况下,当前工作目录将包含在搜索路径列表中。但是,如果您依赖于此,您的应用程序将会工作与否,具体取决于用户启动应用程序时当前的工作目录。在默认情况下,ironpython 将在搜索路径中包含两条与应用程序本身安装位置相关的路径:在上面的输出中可以看到的lib和dll路径。这些位置是将模块与主应用程序保持在一起的好选择。

ironpython 实现使用 assembly.getentryassembly() 函数来获取主机的路径,以便添加 “lib” 和 “dll” 路径。有些情况下,assembly.getentryassembly()将返回 null,这些路径将不会被添加。一个这样的情况是,当环境是 asp.net。

标准库

在您的应用程序中使用标准库并不困难。包含标准库的单独的nuget包可用。这个包将所有的标准库模块添加到 visual studio 项目中。出现的问题是,应用程序使用的模块需要与它分发。如何做到这一点取决于具体情况。在最简单的情况下,您可以将所需的模块放在与应用程序二进制文件相同的目录中,并将它们一起分发。如果您选择该解决方案,则默认搜索路径应该足够,因为它包含“。” 目录。
现在让我们来看一个使用标准库的脚本的简单例子。完整的例子可以从我们的 github 仓库获得:ironpythontutorials/csharpintegration/pythonscriptexecution4

使用 nuget 获取 ironpython 标准库:ironpython.stdlib
helloworldbase64.py

import base64

originalstring = b"hello world!"
print("originalstring:" + str(originalstring))

encodedstring = base64.b64encode(originalstring)
print("encodedstring:" + str(encodedstring))

decodedstring = base64.b64decode(encodedstring);
print("decoded string:" + str(decodedstring))

c#

static void main(string[] args)
{
    var pythonengin = ironpython.hosting.python.createengine();
    console.writeline("search paths:");
    var searchpaths = pythonengin.getsearchpaths();
    foreach (var path in searchpaths)
    {
        console.writeline(path);
    }
    console.writeline();

    searchpaths.add("..\\..\\lib");
    pythonengin.setsearchpaths(searchpaths);

    var pythonscript = pythonengin.createscriptsourcefromfile("..\\..\\helloworldbase64.py");
    pythonscript.execute();
}

输出

search paths:
.
c:\users\hippiezhou\documents\projects\ironpythontutorials\04_pythonscriptexecution4\bin\debug\lib
c:\users\hippiezhou\documents\projects\ironpythontutorials\04_pythonscriptexecution4\bin\debug\dlls

originalstring:hello world!
encodedstring:sgvsbg8gv29ybgqh
decoded string:hello world!

共享变量

在 microsoft.scripting.hosting.scriptscope 类用于保存的是当前在范围内的变量及其关联值列表。本 scriptscope 类提供的方法来设置,获取和范围删除变量。他们是 setvariable, getvariable 和 removevariable。要获取范围中所有变量的列表,请使用getvariablenames 方法。
在我们最开始的例子中,我们使用 pythonscript.execute(); 来运行脚本。无参数 execute() 函数在 scriptscope 内部创建实例,因此调用者无法访问它。但是,我们可以使用其他重载来创建 scriptscope 自己并将其传递给 execute() 函数。
以下示例显示了如何使用这些函数。完整的例子可以从我们的github仓库获得:ironpythontutorials/csharpintegration/pythonscriptexecution5

program.cs

static void main(string[] args)
{
    var pythonengin = ironpython.hosting.python.createengine();
    var pythonscript = pythonengin.createscriptsourcefromstring(
        "helloworldstring='hello world!'\n" + 
        "print(helloworldstring) \n" + 
        "print(extrnalstring)");

    var scope = pythonengin.createscope();
    scope.setvariable("extrnalstring", "how are you.");
    pythonscript.execute(scope);
    console.writeline();
    console.writeline("list of variables in the scope:");
    foreach (var name in scope.getvariablenames())
    {
        console.write(name+ "   ");
    }
    console.writeline();
    console.writeline("variable values:");
    console.writeline("helloworldstring:" + scope.getvariable("helloworldstring"));
    console.writeline("extrnalstring:" + scope.getvariable("extrnalstring"));

    console.readkey();
}

输出

hello world!
how are you.

list of variables in the scope:
extrnalstring   __builtins__   __file__   __name__   __doc__   helloworldstring
variable values:
helloworldstring:hello world!
extrnalstring:how are you.

在这个例子中,脚本定义了这个 helloworldstring 变量,并使用了一个 externalstring 在脚本中没有定义的变量 。然后打印这两个变量。
该 externalstring 变量显示了c# 代码如何使用该 setvariable 方法将变量添加到脚本可以使用的范围。
脚本执行后,范围包含由脚本添加的变量列表。c# 代码使用我们前面提到的各种函数来打印执行后的范围内的内容。

导入模块

在本教程前面,我们看到了 python 脚本如何使用 python import 语句,只要搜索路径设置正确,就可以像任何常规的 python 脚本一样使用python 语句。在这里我们提出另一个有趣的方法,即从 c# 代码中导入模块,而不是 python 代码。
静态 ironpython.hosting.python.importmodule 函数可以用来导入一个模块。它返回 scriptscope 包含导入模块中所有变量的类的一个实例。该 scriptscope 在上面有解释。例如,您可以使用返回的作用域并将其传递给 scriptsource.execute 函数,以执行另一个可以使用导入模块的功能的 python 脚本,甚至可以使用它直接从 c# 执行 python 方法,如下面的示例所示。
将 importmodule 搜索路径中的模块作为 python import 语句进行查找将会这样做,重要的是正确设置路径或找不到模块。
以下示例显示了如何在 python 模块中定义的函数可以像 c# 函数一样执行。

helloworldmodule.py

def printhelloworld():
    print("hello world!")

def printmessage(message):
    print(message)

def add(arg1,arg2):
    return (arg1 + arg2)

program.cs

static void main(string[] args)
{
    var pythonengin = ironpython.hosting.python.createengine();
    var searchpaths = pythonengin.getsearchpaths();
    searchpaths.add("..\\..");
    pythonengin.setsearchpaths(searchpaths);

    var scope = ironpython.hosting.python.importmodule(pythonengin, "helloworldmodule");

    dynamic printhelloworldfunction = scope.getvariable("printhelloworld");
    printhelloworldfunction();

    dynamic printmessagefunction = scope.getvariable("printmessage");
    printmessagefunction("goodbye!");

    dynamic addfunction = scope.getvariable("add");
    console.writeline("the sum of 1 and 2 is " + addfunction(1,2));

    console.readkey();
        }

总结

官网给的示例教程是 visual studio 2013 + python 2.x 版本的,对于 visual studio 2017 + python 3.x 版本的使用方式影响不大。按照官网描述一步一步还是可以完成整个的基本教程。
个人理解:ironpython 其实就是相当于将 python 编译成字节码,然后通过 ironpython 创建的虚拟 python 运行环境(类似虚拟机)从而达到能够运行 python 的目的。经过个人(不科学的)测试,这种模式的运行效率并不是很高,在 python 慢的基础上还要慢一个节拍。所以,想在生产环境中使用的话需要慎重考虑。

参考

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网