2007/04/18

Python und .NET - IronPython

Da ich meine Tantiemen bekanntlich mit .NET verdiene habe ich letztens ein wenig mit IronPython - einer Python Implementation für die CLR - experimentiert. Richtig, in Sachen dynamische Sprachen ist mein Favorit Ruby. Aber schliesslich ist IronPython ja der ‚proof-of-concept’ einer dynamischen Sprache für die CLR, ist komplett in C# geschrieben und läuft auf dem .NET Framework 2.0 und auf Mono. Ausserdem wird eine mühelose, bidirektionale Integration mit ‚managed code’ versprochen. Gründe genug also meine Hirnzellen mit etwas syntaktischen Neuerungen bemühen zu dürfen.

Die Python-Syntax ist ein wenig gewöhnungsbedürftig. So sind zum Beispiel die Einrückungen von Bedeutung. Sie ersetzen die geschweiften Klammern die wir zum Beispiel von C# her kennen.

Eine Methode kann also zum Beispiel folgendermassen definiert werden:

>>> def addOne(x):
...   return x+1
...
>>> print addOne(2)
3

Eine triviale Klasse so:

>>> class MyClass(object):
...   def doSomething():
...     return 'in doSomething'
...

Wir können die Methoden einer Klasse mit der Methode ‚dir’ inspizieren. Als Rubyisten werden wir mit Reflection-Features natürlich geradezu verwöhnt.

>>> t = MyClass()
>>> dir(t)
['__class__', '__dict__', '__doc__', '__init__', '__module__', '__new__', '__red
uce__', '__reduce_ex__', '__repr__', '__weakref__', 'doSomething']

Meine Methode war also korrekt eingerückt. Vererbung ist natürlich auch möglich:

>>> class MySecondClass(MyClass):
...   pass
...
>>> dir(MySecondClass)
['__class__', '__dict__', '__dict__', '__doc__', '__init__', '__module__', '__ne
w__', '__reduce__', '__reduce_ex__', '__repr__', '__weakref__', 'doSomething']

Aber wir wollen jetzt etwas von .NET sehen. Fangen wir an mit Datenstrukturen. Am besten mit einem Hash. Genauer: Einer .NET-Hashtable in IronPython. Nach einigen Gehversuchen sieht das dann so aus:


C:\Program Files\IronPython-1.0.1>ipy.exe
IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42
Copyright (c) Microsoft Corporation. All rights reserved.
>>> import System
>>> from System.Collections import *
>>> h = Hashtable()
>>> h["a"] = "Ruby"
>>> h["b"] = "Smalltalk"
>>> h["c"] = "IronPython"
>>> for e in h: print e.Key, ":", e.Value
...
a : Ruby
b : Smalltalk
c : IronPython

Das ist doch schon mal etwas. .NET-Datentypen und Python-Syntax. Eine aus sozialer Sicht durchwegs tolerante Hochzeit. Um weitere .NET-Bibliotheken benutzen zu können, müssen wir aber das CLR-Modul laden und die einzelnen Referenzen hinzufügen. Im Moment geschieht also noch folgendes:


>>> d = XmlDocument()
Traceback (most recent call last):
File , line 0, in ##11
NameError: name 'XmlDocument' not defined

Wenn wir versuchen den Namespace zu importieren geschieht auch noch nicht viel mehr:

>>> from System.Xml import *
Traceback (most recent call last):
File , line 0, in ##12
File , line 0, in __import__##4
ImportError: No module named Xml

Aha. Das Modul, resp. die Referenz muss also erst hinzugefügt werden. So wie wir es in .NET-Code auch tun würden. Allerdings müssen wir hier erst noch das CLR-Modul laden damit wir diese Referenzen richtig hinzufügen können:


>>> import clr
>>> clr.AddReference("System.Xml")
>>> from System.Xml import *
>>> d = XmlDocument()
>>> d.ToString()
'System.Xml.XmlDocument'

Eigene .NET-Bibliotheken lassen sich übrigens ganz ähnlich importieren:


>>> import clr
>>> clr.AddReferenceToFile("mylibrary.dll")

Um jedoch auch WinForms-Komponenten benutzen zu können und zum Beispiel ein Form anzuzeigen müssen wir dafür sorgen dass der ‚Message-Loop’ richtig behandelt wird. Dazu finden wir nach der Installation von IronPython ein Batch-File ‚winforms.py’ im Unterverzeichnis ‚Tutorial’ welches einen entsprechenden Thread eröffnet und dies sicherstellt.

Alles in allem lässt sich sagen, dass IronPython sicher ein interessantes Projekt ist. Es zeigt dass die CLR auch eine mächtige Plattform für dynamische Sprachen sein kann. Natürlich gefällt mir die Syntax und der Stil von Ruby besser. Das wird sich auch nicht ändern. Aber zumindest als kleine Versuchsumgebung für .NET werde ich sicher in Zukunft das eine oder andere Mal IronPython zu Rate ziehen.

1 comment:

Anonymous said...

You write very well.