githubEdit

在 Zero-Touch 節點中執行 Python 指令碼 (C#)

在 Zero-Touch 節點中執行 Python 指令碼 (C#)

如果您能輕鬆地以 Python 撰寫指令碼,也想要從標準 Dynamo Python 節點獲得更多功能,我們可以使用 Zero-Touch 建立自己的指令碼。我們先從一個簡單的範例開始,我們將一個 Python 指令碼做為字串傳入執行指令碼並傳回結果的 Zero-Touch 節點。此案例研究以「入門」區段中的逐步解說和範例為基礎,如果您是初次建立 Zero-Touch 節點,請參閱這些內容。

將執行 Python 指令碼字串的 Zero-Touch 節點

Python 引擎

如果您從 CPython 移轉,PythonNet3 現在是預設引擎,可提供更順暢的體驗。所有在 Dynamo 4.0+ 中建立的新 Python 節點都從 PythonNet3 開始。

此節點依賴一個 IronPython 指令碼引擎例證。若要執行,我們需要參考一些其他組合。請遵循以下步驟,在 Visual Studio 中設定基本樣板:

  • 建立新的 Visual Studio 類別專案

  • 在位於 C:\Program Files (x86)\IronPython 2.7\IronPython.dllIronPython.dll 中加入參考

  • 在位於 C:\Program Files (x86)\IronPython 2.7\Platforms\Net40\Microsoft.Scripting.dllMicrosoft.Scripting.dll 中加入參考

  • 在您的類別中包括 IronPython.HostingMicrosoft.Scripting.Hosting 兩個 using 陳述式

  • 加入一個空的私用建構函式,以防止額外的節點隨著我們的套件被加到 Dynamo 資源庫

  • 建立一個採用單一字串做為輸入參數的新方法

  • 在此方法中,我們將實體化新的 Python 引擎,並建立空的指令碼範圍。您可以將此範圍想像為 Python 解譯器例證內的全域變數

  • 接下來,在引擎呼叫 Execute,並傳入輸入字串和範圍做為參數

  • 最後,在範圍呼叫 GetVariable,並從包含您嘗試傳回之值的 Python 指令碼傳入變數名稱,來擷取並傳回指令碼的結果。(請參閱以下範例,以取得進一步的詳細資料)

以下程式碼提供上述步驟的範例。建置方案會在專案的 bin 資料夾中建立一個新的 .dll。現在,此 .dll 可匯入至 Dynamo 做為套件的一部分,或瀏覽至「File < Import Library...

Python 指令碼傳回變數 output,這表示我們在 Python 指令碼中需要一個 output 變數。請使用此範例指令碼測試 Dynamo 中的節點。如果您曾在 Dynamo 中使用過 Python 節點,以下內容應該看起來很熟悉。如需更多資訊,請參閱 Primer 的 Python 一節arrow-up-right

多個輸出

標準 Python 節點的一個限制是它們只有單一輸出埠,因此,如果我們希望傳回多個物件,則必須建構清單並擷取其中的每個物件。如果我們修改上述範例以傳回字典,就可以加入任意數目的輸出埠。請參閱〈深入瞭解 Zero-Touch〉中的〈傳回多個值〉一節,以取得有關字典的更多詳細資料。

此節點可讓我們傳回立方體的體積及其形心。

接下來使用以下步驟修改先前的範例:

  • 從 NuGet 套件管理員加入 DynamoServices.dll 的參考

  • 除了先前的組合,還包括 System.Collections.GenericAutodesk.DesignScript.Runtime

  • 修改方法的傳回類型,以傳回包含輸出的字典

  • 每個輸出都必須從範圍中單獨擷取 (請考慮為較大的輸出集設定簡單迴路)

我們也在範例 Python 指令碼中加入其他輸出變數 (output2)。請記住,這些變數可以使用任何合法的 Python 命名慣例,在此範例中是為了清楚起見,所以只使用 output。

PythonNet3 已知的限制和解決方法

以下是使用 PythonNet3 時的一些已知限制和解決方法

  • .NET 集合不會自動轉換為 Python 清單

    • 在使用 len()、索引或迭代之前,必須使用 list(...) 明確轉換 .NET 陣列或集合。

  • 一般 .NET 方法可能需要明確的類型參數

    • 除非您手動指定一般類型而不是依賴自動推斷,否則某些方法 (例如 GroupBy) 會失敗。

  • 透過 dir() 或自動完成無法探索延伸方法

    • 延伸方法在明確呼叫時可能仍然有作用,但不會在自省或程式碼完成時出現。

  • 不支援 DataTable 延伸方法

    • 匯入 System.Data.DataTableExtensions 失敗;這些輔助工具方法不能直接使用。

  • 某些 Dynamo 核心方法在 PythonNet3 中的行為不同

    • 由於集合處理比較嚴格,因此某些功能 (例如清單展開) 可能無法如預期般運作。

  • 如果 Python 類別是從 .NET 類型繼承,則無法在節點之間傳遞類別

    • 從 .NET 類型或介面衍生的類別無法在 Python 節點之間安全地轉移。

  • Python set() 不接受某些 .NET 物件

    • 諸如 InvalidElementId 之類的物件必須篩選掉或改用 .NET 集合處理。

  • 頻繁呼叫 print() 可能會導致記憶體增長

    • 請避免在迴圈或長時間執行的腳本中大量使用 print()

  • Dynamo 與 Python 之間的字典互通性有限

    • Dynamo 字典和 Python 字典無法完全互換,可能需要手動轉換。

  • 無法再使用 Marshal.GetActiveObject() 方法取得指定物件正在執行的 COM 例證

    • 如果您知道使用中檔案的路徑,請使用 BindToMoniker

    • 使用 C# 的 Marshal.GetActiveObject() 類別結構撰寫資源庫程式碼

從 CPython3 移轉至 PythonNet3

Dynamo 會自動將 CPython 節點移轉至 PythonNet 3。以下是發生的情況:

  1. 自動建立原始檔的備份複本。

  2. 所有 CPython 節點 (包括使用 CPython 的自訂節點) 都轉換為 PythonNet3。

  3. 出現一則快顯通知讓您知道移轉的節點數。

  4. 儲存時,您會看到一個提醒,指出您的 Python 節點現在將使用 PythonNet3。您同樣不須擔心向下相容性:對於在多版本產品 (例如,Revit 或 Civil 3D 2025/2026) 中工作的使用者,請在 Dynamo 3.3-3.6 中安裝 PythonNet3 引擎套件以維持相容性。

從 IronPython2 移轉至 PythonNet3

如果您的圖表使用 IronPython 引擎,則不會自動移轉。

如果安裝相符的 IronPython 套件,圖表會正常執行。如果缺少套件,您會在「工作區參考」延伸中看到要求您下載套件的相依性警告。您可以重新安裝套件以繼續使用 IronPython。但是,由於 IronPython 已經好幾年沒有更新,而且 Dynamo 也已經有一段時間沒有積極支援這些引擎,我們強烈建議您移轉到 PythonNet3,確保您的圖表可以繼續可靠地運作。雖然 DynamoIronPython2.7 和 DynamoIronPython3 會繼續以套件的形式在 Dynamo Package Manager 中提供,但 Dynamo 團隊不會再加以維護。

在此情況下,您可以利用 Python 編輯器中的「移轉助理」,將節點逐一進行移轉。

如需有關移轉的更多資訊,請參閱此部落格arrow-up-right

Last updated