在.Net Framework中调用Python的脚本方法 (以VB和C#为例)

某个项目中涉及到这样一个情景: VB/C#写的原始项目要调用Python的一些方法完成特殊的操做, 那么这就涉及到了,在.Net Framework中如何调用Python的脚本方法。python

具体步骤流程以下所示:git

1): 展现一个简单的Python代码,即传递一个参数,而后返回修改后字符串,此文件名称为 mytest.pygithub

def MyTestFunction(name):
    return "testing " + name

2): 咱们借助第三方的工具来实现这个操做,那么这个第三方工具就是 IronPython,IronPython是一种在.Net及Mono上的Python实现,是一个基于微软的DLR引擎的开源项目,能够去这里下载或者跟踪源代码(https://github.com/IronLanguages/ironpython2)。 而后咱们能够到这个连接中下载安装文件(https://github.com/IronLanguages/ironpython2/releases/tag/ipy-2.7.8), 安装文件安装完以后咱们能够到对应的安装目录下面找到咱们所须要的dll(IronPython.dll, IronPython.Modules.dll, Microsoft.Dynamic.dll, Microsoft.Scripting.dll)以及一个名为Lib的文件夹,以下图所示:app

3):咱们用VS建立一个VB的工程,而后将上面的这四个dll引用进来,以后就能够进行具体的调用了,假设咱们的Python代码文件放置的目录是 D:\Code\PyTest\mytest.py 必要时请将此文件copy到VB执行目录中, 而后把对应的pythonPath换掉ide

以下代码所示:wordpress

Imports IronPython.Hosting
Imports Microsoft.Scripting.Hosting

Public Class Form1
    Private Sub CallPython()
        Dim pythonPath = "D:\Code\PyTest\mytest.py"
        Dim pyruntime as ScriptRuntime = Python.CreateRuntime()
        Dim fileObj As Object = pyruntime.UseFile(pythonPath)
        Dim result = fileObj.MyTestFunction("World")
    End Sub
End Class

这样咱们就经过IronPython完成了VB调用Python脚本方法,咱们能够继续参考以下链接: https://blog.csdn.net/letunihao/article/details/41985163工具

 

这里Python的脚本方法很是单纯无暇,没有任何的其余脚本的引用, 可是实际项目中这样单纯的代码大可能是没有意义的,总会引用其余的module来实现更加复杂的逻辑。测试

下面咱们就要进阶了,若是Python脚本之间有相互的引用,如何完成咱们的目标呢?请看以下步骤spa

4):在相同的目录中建立另一个Python文件来实现文件的读写,文件名为 mytest_common.py,.net

import os

class FileOperator:
    
    def WriteInfoToFile(self, path):
        file = open(path, "w")
        file.write("Hello World")
        file.close()

    def ReadInfoFromFile(self, path):
        fileInfo = ""
        data = open(path)
        for each_line in data:
            fileInfo += each_line
        data.close()
        return fileInfo

为何实现方法的时候要加入一个额外的参数 self?

请看以下链接: https://stackoverflow.com/questions/23944657/typeerror-method-takes-1-positional-argument-but-2-were-given/42016399

文件读写请参考 (http://www.pythonforbeginners.com/files/reading-and-writing-files-in-python)

 

5):而后咱们对 mytest.py 文件作以下修改,假设咱们已经经过Python本身运行WriteInfoToFile方法已经生成了一个Test.txt文件

from mytest_common import FileOperator

def MyTestReadInfo():
    fInfo = fOperator.ReadInfoFromFile("D:\Code\PyTest\Test.txt")
    return fInfo

fOperator = FileOperator()

6):而后咱们用以下VB代码进行对新的Python脚本方法的调用

Imports IronPython.Hosting
Imports Microsoft.Scripting.Hosting

Public Class Form1
    Private Sub CallPython()
        Dim pythonPath = "D:\Code\PyTest\mytest.py"
        Dim pyruntime as ScriptRuntime = Python.CreateRuntime()
        Dim fileObj As Object = pyruntime.UseFile(pythonPath)
        Dim result = fileObj.MyTestReadInfo()
    End Sub
End Class

会throw exception说:某某某某module没法加载, 或者是找不到某某module。Unhandled Exception: IronPython.Runtime.Exceptions.ImportException: No module named ... 缘由是:Python本身运行的时候会自动加载对应相关联的module,特别是一些系统的module,好比这里面的 os, 可是咱们经过外部调用的时候没法自动创建这样的连接,由于咱们要在Python的源文件中明确指明所引用的那些系统源文件所在folder,让其能够在指定的folder下面去寻找相关联的源文件。

那么这些源文件在什么地方呢?咱们能够到Python的安装目录下寻找,也能够到咱们第2步 IronPython的安装目录下面寻找,即Lib文件夹,而后将此文件夹copy到咱们的测试Python的同级文件夹,用相对路径指定,固然你也能够不用copy,而后用绝对路径定位到Lib文件夹便可

代码以下所示:

import sys
sys.path.append(".\Lib")

from mytest_common import FileOperator

def MyTestReadInfo():
    fInfo = fOperator.ReadInfoFromFile("D:\Code\PyTest\Test.txt")
    return fInfo

fOperator = FileOperator()

这样咱们再用第6步中的VB代码去调用就能够成功了。

注:使用相对路径时,请注意使用文件的位置,保证可以成功定位到。

更多详细信息能够参考以下链接:

https://stackoverflow.com/questions/6195781/ironpython-exe-compiled-using-pyc-py-cannot-import-module-os

https://thesesergio.wordpress.com/2013/09/11/how-to-generate-and-use-a-exe-that-uses-net-dlls-with-ironpython-pyc-py/

https://blog.csdn.net/letunihao/article/details/41985163

 

 

给出C#部分代码以做参考

        public static dynamic GetPythonFileObj()
        {
            var fath = AppContext.BaseDirectory + @"Services\PythonService.py";

            var pyruntime = Python.CreateRuntime();
            var pyengine = pyruntime.GetEngine("Python");
            var paths = pyengine.GetSearchPaths();
            paths.Add(AppContext.BaseDirectory + @"Services");
            paths.Add(AppContext.BaseDirectory + @"Services\Lib");
            pyengine.SetSearchPaths(paths);

            dynamic fileObj = pyruntime.UseFile(fath);
            return fileObj;
        }


        public static string UploadTag(ref dynamic fileObj, string tagName)
        {
            var tagValue = fileObj.ex_read(tagName);
            return tagValue.ToString();
        }
View Code
相关文章
相关标签/搜索