IronPython初體驗

来源:https://www.cnblogs.com/hippieZhou/archive/2018/11/02/9898226.html
-Advertisement-
Play Games

介紹 在 C# 程式中嵌入 IronPython 得到了很好的支持。在本教程中,我們將展示如何完成這個項目。 首先,我們將展示兩個非常基本的例子,說明如何執行一個不導入任何模塊的非常簡單的腳本。然後,再展示如何執行使用模塊的腳本。 在 C 中執行 Python 第一個例子 我們來創建一個執行Pyth ...


介紹

在 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

如果你想瞭解更多關於在幕後發生的事情,你可以看看 IronPython Internals Foundations tutorial.

第二個例子

第二個例子與第一個例子幾乎相同,但是我們將使用 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 慢的基礎上還要慢一個節拍。所以,想在生產環境中使用的話需要慎重考慮。

參考

  1. IronPython C# Integration

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 工作中後臺開發使用的是 TP5,但是對語法不是很熟悉,總是看著手冊寫代碼。當時做 Java 的時候也是這樣,很多語法需要靠百度。不是不能寫代碼,但是這樣的效率感覺不高,沒有行雲流水的感覺,要是能有聊天時打字的感覺就好多了。不熟悉就得多學習,但是學完經常就忘記了,所以博客就當是記錄了。 TP5的驗證碼 ...
  • java 8日期相關類 Instant:時間戳 Duration:持續時間,時間差 LocalDate:只包含日期,比如:2016 10 20 LocalTime:只包含時間,比如:23:12:10 LocalDateTime:包含日期和時間,比如:2016 10 20 23:14:21 Perio ...
  • 文件操作:讀取 r rb、只寫 w wb、追加 a ab、r+、w+、a+ 功能詳解:seek、tell、readable、readline、readlines、truncate、with as ...
  • 《Accelerated C++ 中文版通過示例進行編程實踐》系統介紹C++程式設計,是美國斯坦福大學的經典教材。從使用C++標準庫中的高級抽象開始,使讀者很快掌握編程方法。每一章都有很經典獨特的例子以及非常到位的講解,覆蓋了C++更多領域的內容,從標準庫容器、泛型演算法的使用,到類的設計、泛型演算法的 ...
  • 環境安裝 環境安裝 主要包含三個部分 運行環境及開發sdk 系統環境和路徑配置 IDE配置 以mac環境為例,其他環境類似 運行環境及開發sdk 使用 brew 安裝 檢查,得到go基本安裝信息 系統環境和路徑配置 主要是GOROOT和GOPATH GOROOT:就是go的安裝環境 GOPATH:作 ...
  • Spring 是一個非常流行的基於Java語言的開發框架,此框架用來構建web和企業應用程式。與許多其他僅關註一個領域的框架不同,Spring框架提供了廣泛的功能,通過其組合項目滿足現代業務需求。 Spring框架提供了以多種方式配置bean的靈活性,例如XML,註解和JavaConfig。隨著功能 ...
  • 內置函數: continue... 傳送門 ...
  • 1、作用域相關 locals() 功能:返回當作用域中的名字 globals() 功能:返回全局作用域中的名字 2、迭代器/生成器相關 range() 功能:生成數據 iter() 功能:獲取迭代器,內部實際使用的是__iter__()方法來獲取迭代器 next() 功能:迭代器向下執行一次,內部實 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...