arrow-left

All pages
gitbookPowered by GitBook
1 of 1

Loading...

Exécuter des scripts Python dans des nœuds Zero-Touch (C#)

hashtag
Exécuter des scripts Python dans des nœuds Zero-Touch (C#)

Si vous êtes à l’aise avec l’écriture de scripts en Python et que vous voulez plus de fonctionnalités à partir des nœuds Python standard de Dynamo, nous pouvons utiliser Zero-Touch pour créer les nôtres. Commençons par un exemple simple qui nous permet de faire passer un script python sous la forme d’une chaîne à un nœud Zero-Touch où le script est exécuté et un résultat est renvoyé. Cette étude de cas s’appuie sur les guides et les exemples de la section Mise en route. Reportez-vous à ces derniers si vous êtes novice en matière de création de nœuds Zero-Touch.

Un nœud Zero-Touch qui exécute une chaîne de script Python

hashtag
Moteur Python

PythonNet3 est désormais le moteur par défaut avec une expérience plus fluide si vous migrez depuis CPython. Tous les nouveaux nœuds Python créés dans Dynamo 4.0 et versions ultérieures commencent par PythonNet3.

Ce nœud s’appuie sur une instance du moteur de script IronPython. Pour faire cela, nous devons référencer quelques assemblages supplémentaires. Suivez les étapes ci-dessous pour configurer un modèle de base dans Visual Studio :

  • crĂ©ez un projet de classe Visual Studio ;

  • ajoutez une rĂ©fĂ©rence au IronPython.dll situĂ© dans C:\Program Files (x86)\IronPython 2.7\IronPython.dll ;

  • ajoutez une rĂ©fĂ©rence au Microsoft.Scripting.dll

Le code suivant fournit un exemple pour l’étape mentionnée ci-dessus. La génération de la solution entraîne la création d’un nouveau .dll situé dans le dossier bin de notre projet. Ce .dll peut désormais être importé dans Dynamo en tant que composant d’un package ou en accédant à File < Import Library...

Le script Python renvoie la variable output, ce qui signifie que vous aurez besoin d’une variable output dans le script Python. Utilisez cet exemple de script pour tester le nœud dans Dynamo. Si vous avez déjà utilisé le nœud Python dans Dynamo, ce qui suit devrait vous sembler familier. Pour plus d’informations, consultez la .

hashtag
Sorties multiples

L’une des limites des nœuds Python standard est qu’ils n’ont qu’un seul port de sortie. Si nous souhaitons renvoyer plusieurs objets, nous devons construire une liste et récupérer chaque objet à l’intérieur. Si nous modifions l’exemple ci-dessus pour qu’il renvoie un dictionnaire, nous pouvons ajouter autant de ports de sortie que nous le souhaitons. Reportez-vous à la section Renvoyer plusieurs valeurs dans Aller plus loin avec Zero-Touch pour plus de détails sur les dictionnaires.

Ce nœud permet de renvoyer le volume du cuboïde et son centre de gravité.

Modifions l’exemple précédent en procédant comme suit :

  • ajoutez une rĂ©fĂ©rence DynamoServices.dll du gestionnaire de package NuGet ;

  • en plus des assemblages prĂ©cĂ©dents, incluez System.Collections.Generic et Autodesk.DesignScript.Runtime ;

Nous avons également ajouté une variable de sortie supplémentaire (output2) à l’exemple de script Python. N’oubliez pas que ces variables peuvent utiliser n’importe quelle convention de dénomination légale de Python. La sortie a été utilisée uniquement pour des raisons de clarté dans cet exemple.

hashtag
Limitations connues de PythonNet3 et solutions de contournement

Voici quelques limitations connues et des solutions de contournement à appliquer lors de l’utilisation de PythonNet3

  • Les collections .NET ne sont pas automatiquement converties en listes Python

    • Vous devez convertir explicitement les tableaux ou les collections .NET Ă  l’aide de list(...) avant d’utiliser len(), en indexation ou en itĂ©ration.

hashtag
Migration de CPython3 vers PythonNet3

Dynamo migrera automatiquement les nœuds CPython vers PythonNet3, suivant les étapes ci-après :

  1. Une copie de sauvegarde du fichier d’origine est créée automatiquement.

  2. Tous les nœuds CPython (y compris les nœuds personnalisés qui utilisent CPython) sont convertis en PythonNet3.

  3. Une notification évanescente vous permet de savoir combien de nœuds ont été migrés.

hashtag
Migration d’IronPython2 vers PythonNet3

Si votre graphique utilise un moteur IronPython, la migration n’est pas automatique.

Si le package IronPython correspondant est installé, votre graphique s’exécute normalement. S’il est absent, un avertissement de dépendance s’affiche dans l’extension de références de l’espace de travail vous demandant de télécharger le package. Vous pouvez continuer à utiliser IronPython en réinstallant le package. Mais comme IronPython n’a pas été mis à jour depuis plusieurs années et que Dynamo ne prend pas activement en charge ces moteurs depuis un certain temps, nous vous recommandons vivement de migrer vers PythonNet3 pour vous assurer la fiabilité de vos graphiques à l’avenir. Bien que les packages DynamoIronPython2.7 et DynamoIronPython3 restent disponibles dans le gestionnaire de package Dynamo, ils ne seront plus entretenus par l’équipe Dynamo.

Dans ce cas, vous devrez effectuer la migration nœud par nœud à l’aide de l’assistant de migration disponible dans l’éditeur Python.

Pour en savoir plus sur la migration, consultez ce

situé dans
C:\Program Files (x86)\IronPython 2.7\Platforms\Net40\Microsoft.Scripting.dll
;
  • incluez les instructions IronPython.Hosting et Microsoft.Scripting.Hosting using dans votre classe ;

  • ajoutez un constructeur privĂ© vide pour empĂŞcher l’ajout d’un nĹ“ud supplĂ©mentaire Ă  la bibliothèque Dynamo avec votre package ;

  • crĂ©ez une mĂ©thode qui prend une seule chaĂ®ne comme paramètre d’entrĂ©e ;

  • dans cette mĂ©thode, nous allons instancier un nouveau moteur Python et crĂ©er une portĂ©e de script vide. Vous pouvez imaginer cette portĂ©e comme les variables globales dans une instance de l’interprĂ©teur Python ;

  • appelez ensuite Execute sur le moteur en passant la chaĂ®ne d’entrĂ©e et la portĂ©e comme paramètres ;

  • enfin, rĂ©cupĂ©rez et renvoyez les rĂ©sultats du script en appelant GetVariable sur la portĂ©e et en transmettant le nom de la variable de votre script Python qui contient la valeur que vous essayez de renvoyer (Voir l’exemple ci-dessous pour plus de dĂ©tails).

  • modifiez le type de retour de notre mĂ©thode pour qu’elle renvoie un dictionnaire qui contiendra nos rĂ©sultats ;
  • chaque sortie doit ĂŞtre extraite individuellement de la portĂ©e (il est conseillĂ© de configurer une boucle simple pour des ensembles de sorties plus importants).

  • Les mĂ©thodes .NET gĂ©nĂ©riques peuvent nĂ©cessiter des paramètres de type explicites
    • Pour que certaines mĂ©thodes (p. ex. GroupBy) rĂ©ussissent, vous devrez spĂ©cifier manuellement les types gĂ©nĂ©riques au lieu d’avoir recours Ă  l’infĂ©rence automatique.

  • Les mĂ©thodes d’extension ne sont pas dĂ©tectables par l’intermĂ©diaire de dir() ou de la saisie semi-automatique

    • Les mĂ©thodes d’extension peuvent toujours fonctionner lorsqu’elles sont appelĂ©es explicitement, mais elles n’apparaissent pas dans l’introspection ni dans la complĂ©tion de code.

  • Les mĂ©thodes d’extension DataTable ne sont pas prises en charge

    • L’importation de System.Data.DataTableExtensions Ă©choue. Ces mĂ©thodes d’assistance ne peuvent pas ĂŞtre utilisĂ©es directement.

  • Certaines mĂ©thodes fondamentales de Dynamo se comportent diffĂ©remment dans PythonNet3

    • Certaines fonctions (p. ex. l’aplanissement de listes) peuvent ne pas fonctionner comme prĂ©vu en raison d’une gestion plus stricte des collections.

  • Les classes Python ne peuvent pas ĂŞtre transmises entre les nĹ“uds si elles hĂ©ritent de types .NET

    • Les classes dĂ©rivĂ©es de types ou d’interfaces .NET ne peuvent pas ĂŞtre transfĂ©rĂ©es correctement entre les nĹ“uds Python.

  • Dans Python, set() n’accepte pas certains objets .NET

    • Les objets comme InvalidElementId doivent ĂŞtre filtrĂ©s ou gĂ©rĂ©s Ă  l’aide de collections .NET Ă  la place.

  • Les appels print() frĂ©quents peuvent entraĂ®ner une croissance de la mĂ©moire

    • Évitez l’utilisation intensive de print() dans des boucles ou des scripts longs Ă  exĂ©cuter.

  • L’interopĂ©rabilitĂ© des dictionnaires entre Dynamo et Python est limitĂ©e

    • Les dictionnaires Dynamo et Python ne sont pas entièrement interchangeables et peuvent nĂ©cessiter une conversion manuelle.

  • La mĂ©thode Marshal.GetActiveObject(), qui permettait d’obtenir l’occurrence COM en cours d’exĂ©cution d’un objet spĂ©cifiĂ©, n’est plus disponible

    • Utilisez BindToMoniker si vous connaissez le chemin d’accès au fichier en cours d’utilisation.

    • Codez une bibliothèque en C# Ă  l’aide de la structure de classe Marshal.GetActiveObject()

  • Lors de l’enregistrement, vous verrez un rappel indiquant que vos nĹ“uds Python utiliseront dĂ©sormais PythonNet3. LĂ  encore, ne vous inquiĂ©tez pas de la rĂ©trocompatibilitĂ© : pour ceux qui utilisent plusieurs versions de logiciels (p. ex. Revit ou Civil 3D 2025/2026), installez le package PythonNet3 Engine dans Dynamo 3.3–3.6 pour maintenir la compatibilitĂ©.
    section Python du guidearrow-up-right
    blogarrow-up-right
    using IronPython.Hosting;
    using Microsoft.Scripting.Hosting;
    
    namespace PythonLibrary
    {
        public class PythonZT
        {
            // Unless a constructor is provided, Dynamo will automatically create one and add it to the library
            // To avoid this, create a private constructor
            private PythonZT() { }
    
            // The method that executes the Python string
            public static string executePyString(string pyString)
            {
                ScriptEngine engine = Python.CreateEngine();
                ScriptScope scope = engine.CreateScope();
                engine.Execute(pyString, scope);
                // Return the value of the 'output' variable from the Python script below
                var output = scope.GetVariable("output");
                return (output);
            }
        }
    }
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    cube = Cuboid.ByLengths(10,10,10);
    volume = cube.Volume
    output = str(volume)
    using IronPython.Hosting;
    using Microsoft.Scripting.Hosting;
    using System.Collections.Generic;
    using Autodesk.DesignScript.Runtime;
    
    namespace PythonLibrary
    {
        public class PythonZT
        {
            private PythonZT() { }
    
            [MultiReturn(new[] { "output1", "output2" })]
            public static Dictionary<string, object> executePyString(string pyString)
            {
                ScriptEngine engine = Python.CreateEngine();
                ScriptScope scope = engine.CreateScope();
                engine.Execute(pyString, scope);
                // Return the value of 'output1' from script
                var output1 = scope.GetVariable("output1");
                // Return the value of 'output2' from script
                var output2 = scope.GetVariable("output2");
                // Define the names of outputs and the objects to return
                return new Dictionary<string, object> {
                    { "output1", (output1) },
                    { "output2", (output2) }
                };
            }
        }
    }
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    cube = Cuboid.ByLengths(10,10,10);
    centroid = Cuboid.Centroid(cube);
    volume = cube.Volume
    output1 = str(volume)
    output2 = str(centroid)