在.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
相關文章
相關標籤/搜索