11 août 2021

[Dynamo += IronPython] modules & librairies complémentaires

 



Comment utiliser/ajouter une librairie(module) complémentaire avec IronPython 2.7 ?

if this article is not in your language, use the Google Translate widget (bottom of page for Mobile version)


Compatibilité des modules Python :
à ce jour IronPython ne supporte pas les librairies Python ayant des parties de code (ou dépendance) écrite en C. Pour les librairies écrites en "pur" Python, il faut juste s'assurer de la compatibilité avec la version d'IronPython que vous utilisez.

Bien qu'un projet Ironclad existe pour rendre compatibles les bibliothèques comme numpy avec IronPython, cependant la dernière version compatible avec ce projet est la version 2.7.5. 
En attendant la compatibilité d'Ironclad avec IronPython3 (travaux en cours par la Team IronPython) voici quelques alternatives.

Voici 2 façons d'utiliser des librairies complémentaires avec IronPython.
    1. Utiliser des librairies .Net (Numpy.NET, Math.NET Numerics, etc.)
    2. Utiliser des librairies pures Python (sans dépendance de code écrit en C)

Exemple N°1 


Pour ce premier exemple, prenons une équation linéaire à résoudre (l'objectif est de trouver x, y et z).




  • Solution avec une librairie .Net  (Math .Net Numerics)

Un des moyens de trouver des librairies .Net est de se rendre sur https://www.nuget.org/, de télécharger et décompresser le package désiré et de charger l'assembly dll dans votre nœud Dynamo IronPython.

import sys
import clr
import System
from System import Array
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
sys.path.append(r'D:\DIVERS\SolveLinearEquation')
clr.AddReferenceToFile(r'MathNet.Numerics.dll')

import MathNet.Numerics.LinearAlgebra as la

a = Array.CreateInstance(object, 2, 2)
A = la.Double.Matrix.Build.DenseOfRowArrays(
   Array[float]([3, 2, -1]),
   Array[float]([2, -2, 4]),
   Array[float]([-1, 0.5,-1])
)

b = la.Double.Vector.Build.DenseOfArray(Array[float]([1, -2, 0]))

x = A.Solve(b)

OUT = x 
Résolution d'une équation linéaire avec MatNet


 

  • Solution avec une librairie "pur" Python ("Sympy")

Note :
depuis Dynamo 2.1 l'emplacement de l'installation d'IronPython dédié a Dynamo se trouve désormais dans le dossier DynamoCore au lieu d'être une installation à l'échelle du système. Cela empêchera la version de Python de Dynamo d'interférer avec d'autres outils de votre système qui reposent également sur IronPython.

Une solution consiste à installer des librairies Python supplémentaires à partir d'un répertoire d'installation d'IronPython (ici, nous utiliserons directement l'archive zip 2.7 qui contient toutes les ressources)

Installation des Modules, voici les étapes à suivre (passer les étapes 1 à 3 si déjà effectuées)
        1 - Télécharger l'archive IronPython.2.7.11.zip et décompressée celle-ci en tant que répertoire
        2 - Ouvrir une invite de commande dans le dossier contenant l'exécutable ipy



        3 - Installer l'installeur de paquets pip avec la commande .\ipy -X:Frames -m ensurepip



        4 - Installer les packages dans l'ordre suivant 
                .\ipy -X:Frames -m pip install mpmath==0.19
                .\ipy -X:Frames -m pip install sympy==1.3

Note si cela ne fonctionne pas sous IronPython2.7, vous pouvez essayer directement un pip depuis le zip du repo en copiant l'URL du zip




ipy -X:Frames -m pip install https://github.com/sympy/sympy/archive/refs/tags/sympy-1.3.zip






        5 - Ajouter le chemin du dossier "site-packages" au sys.path dans votre script puis importer le module

le code

  
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
sys.path.append(r'C:Users\sneep\Downloads\IronPython.2.7.11\Lib')
sys.path.append(r'C:Users\sneep\Downloads\IronPython.2.7.11\Lib\site-packages')
from sympy import *
x, y, z = symbols('x, y, z')
eq1 = 3*x + 2*y - z
eq2 = 2*x - 2*y + 4*z
eq3 = -1*x + 0.5*y - z
out = solve([eq1 - 1, eq2 + 2, eq3 - 0], (x, y,z))
print(out)
#
OUT = [[str(x), float(y)] for x,y in out.items()]


Résolution d'une équation linéaire avec sympy


Exemple opération matricielle avec sympy


Exemple N°2

Un autre exemple avec du web scraping / parsing 

  • Solution avec le framework .Net et les interfaces MSHTML

installation des modules
aucun, le Framework .Net et l'assembly mshtml  sont présents avec Windows

 
import clr
import sys
import System
from System.IO import *
from System.Net import *

clr.AddReferenceByName(r'Microsoft.mshtml, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
import mshtml
from mshtml import HTMLDocumentClass

def getResquestContent(urlStr):
	html = None
	request = WebRequest.Create(urlStr)
	with request.GetResponse() as response:	 
		with response.GetResponseStream() as stream:
			with StreamReader(stream) as reader:
				html = reader.ReadToEnd()
				html = html.encode("utf-8")
	return html

out = []
url1= "https://voltadynabim.blogspot.com/"
HTMLcontent = getResquestContent(url1)

htmlDocument = HTMLDocumentClass()
htmlDocument.write(HTMLcontent)
allElements = htmlDocument.body.all
for divCom in  allElements.tags("div"):
	if divCom.className == 'date-outer':
		innerHtml = divCom.innerHTML 
		subhtmlDocument = HTMLDocumentClass()
		subhtmlDocument.write(innerHtml)
		postdiv = subhtmlDocument.GetElementsByTagName("h2")
		date = postdiv[0].InnerText
		adiv = subhtmlDocument.GetElementsByTagName("a")
		# OR 
		# #h3div = subhtmlDocument.body.all.tags("a")
		link = adiv[1].getAttribute("href")
		title = adiv[1].innerText 
		out.append([date, title, link])

OUT = out

  • Solution avec les modules Python beautifulsoup4 et requests

installation des modules
.\ipy -X:Frames -m pip install beautifulsoup4
.\ipy -X:Frames -m pip install requests==2.18.4

 
import clr
import sys
import System

sys.path.append(r'C:\Users\sneep\Downloads\IronPython.2.7.11\Lib\site-packages')
from bs4 import BeautifulSoup # -> .\ipy -X:Frames -m pip install beautifulsoup4
import requests # install -> .\ipy -X:Frames -m pip install requests==2.18.4
from requests.api import get

url1= "https://voltadynabim.blogspot.com/"
r= requests.get(url1)
HTMLcontent= r.content
soup=BeautifulSoup(HTMLcontent, 'html.parser')
out = []

for div in soup.findAll('div', attrs={'class':'date-outer'}):
	date = div.span.text
	childrens = div.findChildren("h3" , recursive=True)
	postblogdict = childrens[0].find('a', href=True)
	link = postblogdict.attrs['href']
	title = postblogdict.text
	out.append([title, date, link] )

OUT = out  



En Conclusion,
à ce jour l'ajout / installation de package sur le moteur IronPython est plus limité que sur le moteur CPython3/PythonNet , cependant IronPython offre l'accès a l'ensemble du framework .Net (y compris l'accès aux COM Interrop, ce qui n'est pas le cas de PythonNet à ce jour).

Cet accès au framework .Net peut dans certains cas vous passez de modules complémentaires, à défaut si vous publiez votre script (exemple sur un serveur) penser à inclure vos modules (dll ou modules Python) ou à minima à référencer les dépendances que ce soit sous IronPython ou CPython/PythonNet


Ressources

0 commentaires:

Enregistrer un commentaire