Daten|teiler
Kopieren als Kulturtechnik

Nicht nur für Zombies: Einstieg in IronPython

1. Juli 2012 von Christian Imhorst
Voraussetzungen:  
   
Betriebssystem: Windows 7
.NET-Framework: Version 4.0
IronPython: Version 2.7.2.1
Evtl. Compiler: Visual Studio Express 2010

Wenn einem IronPython wie ein semi-toter Zombie erscheint, der kaum User hat, liegt das zum großen Teil an IronPython selbst: Es ist ein Nischenprodukt, was Schade ist, und wird das vermutlich auch bleiben, was noch mehr Schade ist, da IronPython wunderbare Einblicke in das.NET-Frameworkgewährt.

Dieser Artikel ist zum ersten Mal in der Ausgabe 07/2012 von freiesMagazin erschienen.

.NET wurde im Jahr 2000 von Microsoft ins Leben gerufen und ist heute eine populäre Plattform für objektorientierte Programmierung unter Windows. Beschäftigt man sich mit IronPython, muss man Python kennen und mögen, was Gerüchten zufolge nicht jedermanns Sache ist. IronPython eignet sich auch nur schlecht dazu, die Programmiersprache selbst zu lernen. Als Anfänger startet man am besten mit der offiziellen Python-Referenz CPython, um sich die Konzepte der Sprache anzueignen. Dann muss man sich noch im .NET-Framework von Microsoft auskennen und sich damit auch beschäftigen wollen. Außerdem ist IronPython für Anwendungen im Geschäftsumfeld so gut wie irrelevant, da Microsoft mit C#, VB.NET und der PowerShell selbst Programmier- und Skriptsprachen für die .NET-Plattform anbietet. Nachdem IronRuby und IronPython im Oktober 2010 an die Open-Source-Community übergeben wurden, ging darüber hinaus auch noch die aktive Unterstützung durch Microsoft verloren, was zur Folge hat, dass IronPython seitdem nicht mehr so schnell weiterentwickelt wird.

Dabei hat IronPython einige spannende Sachen zu bieten, wie zum Beispiel seine Geschichte, warum es überhaupt existiert. Um 2003 herum gab es einige Berichte im Internet, in denen behauptet wurde, dass die Common Language Runtime (CLR), das Herz und die Seele des .NET-Frameworks, für dynamische Sprachen wie Python einfach ungeeignet sei. Jim Hugunin, der zuvor JPython, das heute Jython heißt, für die Java Virtual Machine (JVM) entwickelt hatte, fragte sich deshalb: Was hat Microsoft mit der CLR unter .NET bloß so falsch gemacht, dass sie mit Python nicht funktionieren soll? Er wollte dieser Frage ein paar Wochen lang auf den Grund gehen und am Ende das Ergebnis im Artikel „Why the CLR is a terrible platform for dynamic languages“ zeigen. Zu seiner Überraschung stellte Hugunin aber fest, dass sich Python sehr gut für die CLR eignet. Also erschien 2006 die Version 1.0 von IronPython als vollständig in C# geschriebene Implementierung der Programmiersprache Python. Dabei hält sich IronPython an die in der Programmiersprache C geschriebene Referenz-Implementierung und ist vollständig kompatibel zu CPython. Anfangs stand IronPython noch unter Microsofts eigener Open Source-Lizenz Micosoft Public License, mittlerweile ist es aber zur Apache-Lizenz 2.0 gewechselt.

Da .NET von Anfang an als ein sprachunabhängiges Framework konzipiert worden ist, können Programmierer in unterschiedlichen Programmiersprachen wie C#, VB.NET oder Visual C++ arbeiten. Software, die in diesen .NET-Sprachen geschrieben wurde, wird mithilfe eines Just-In-Time-Compilers in eine Zwischensprache übersetzt, der Common Intermediate Language (CIL), bevor sie von der Laufzeitumgebung CLR ausgeführt wird. IronPython ist in diesem Sinn der .NET-Compiler für eine Programmiersprache namens Python. Wie in .NET üblich, kann man auf Bibliotheken zugreifen, die in anderen .NET-Sprachen geschrieben wurden, und mit Einschränkungen auch umgekehrt. Dazu liefert IronPython den Compiler pyc.py für die Kommandozeile mit, der IronPython-Quellcode in eine .NET-Bibliothek übersetzt. Diese werden in .NET Assemblies genannt und können in anderen .NET-Projekten weiter verwendet werden, egal in welcher Programmiersprache des Frameworks sie geschrieben wurden. Grundsätzlich lässt sich alles, was man mit einer .NET-Sprache wie C# oder VB.NET erreichen kann, auch mit IronPython umsetzen, und genießt dabei noch alle Vorzüge der Programmiersprache Python.

Jetzt kann man meinen, dass der erste Teil des Namens IronPython als Akronym für „It Runs On .Net“ steht. Das passt zwar sehr gut, der Name geht jedoch auf Hugunins alte Beratungsfirma „Want of a Nail Software“ zurück. Wobei „Want of a Nail“ seinen Ursprung in einem Kinderreim hat, der davon handelt, das kleine Dinge im Leben große Auswirkungen haben können. Auch bei IronPython liegt die Aufmerksamkeit bei vielen kleinen Dingen, wie in dem Kindergedicht auf den eisernen Nagel. Außerdem waren die Alternativen wie Python.Net, Python#, nPython laut Hugunin schon vergeben und klangen auch nicht so schön wie IronPython.

Installation

Die aktuelle Windows-Version von IronPython, die Version für Mono soll in diesem Artikel nicht Thema sein, beruht auf .NET Version 4.0, das separat heruntergeladen werden kann und auch benötigt wird, sollte es unter Windows noch nicht durch eine andere Anwendung installiert worden sein. IronPython selbst kann von der Homepage oder direkt bei Codeplex heruntergeladen werden. Wobei der Quellcode, wie auch der von IronRuby, auf Github zu finden ist, bzw. gespiegelt bei BitBucket, wofür sich die Mehrheit der IronPython-Community ausgesprochen hatte, da es auf Mercurial beruht. Die MSI-Datei installiert man einfach durch einen Doppelklick. Danach findet man IronPython unter „C:\Program Files\IronPython 2.7“ im Dateisystem. Der Pfad fehlt allerdings in der Umgebungsvariable PATH, die man entweder unter Systemsteuerung -> System -> Erweiterte Systemeinstellungen bzw. Windows-Taste + Pause und danach unter Umgebungsvariablen… ändert. Man kann stattdessen auch die Befehle set und setx in der Kommandozeile benutzen:

set PATH=C:\Program Files\IronPython 2.7;%PATH%
setx Path "%PATH%" /M
ipy

Der erste Befehl mit SET fügt den Pfad „C:\Program Files\IronPython 2.7“ der Umgebungsvariablen PATH für die aktuelle Sitzung hinzu, durch den zweiten Befehl mit SETX bleibt die Änderungen auch für zukünftige Sitzungen erhalten. Am Ende startet der Befehl ipy oder auch ipy.exe den Interpreter von IronPython.

Der MSI-Installer sollte alle Module der Python-Standard-Bibliothek dabei haben. Falls ein Modul fehlt und CPython parallel zu IronPython auf dem Rechner installiert ist, kann man die Python-Standard-Bibliothek einbinden, indem man im IronPython-Verzeichnis im Unterordner „Lib“ die Datei site.py um folgende Zeile ergänzt; wobei man den Pfad zur Python-Installation eventuell noch anpassen muss:

sys.path.append("C:\Program Files\Python27\Lib")

Hallo Welt!

Als Einstieg in IronPython dient das übliche Hallo-Welt-Programm. Dazu startet man den IronPython-Interpreter, indem man den Befehl ipy in das Suchfenster von Windows 7 oder in der Kommandozeile eingibt oder die „IronPython Console“ unter Start -> Alle Programme -> IronPython 2.7 aufruft. Als erstes fällt einem dabei vielleicht die etwas längere Startzeit des Interpreters auf. Die hängt unter anderem davon ab, dass die komplette .NET-Laufzeitumgebung geladen werden muss. Zum anderen verzögert zusätzlich noch die Just-In-Time-Übersetzung, wenn man ein IronPython-Skript mit dem Befehl ipy mySkript.py startet. Es bleibt zu hoffen, dass sich die Startzeit in zukünftigen Versionen von IronPython verbessert.

Ein kleines Hallo-Welt-Programm ohne eine .NET-Bibliothek sieht in IronPython genauso aus wie in Python selbst:

print "Hallo Welt!"

Das gleiche Beispiel mit WriteLine aus der .NET-Namensraum „System.Console“ sieht schon etwas anders aus:

from System.Console import *
WriteLine("Hallo Welt!")

Wer sich schon einmal mit VB.NET beschäftigen durfte, kommt hier einiges bekannt vor. Der Eindruck verstärkt sich, wenn man die Meldung in einem gesonderten Fenster mit MessageBox ausgeben will:

import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import *
 
MessageBox.Show("Hallo Welt!", \
	"Wichtige Mitteilung", \
	MessageBoxButtons.OK, \
	MessageBoxIcon.Information, \
	MessageBoxDefaultButton.Button1)

Mit dem Importieren des CLR-Moduls erhält man in IronPython die Basisfunktionen für den Zugriff auf .NET-Bibliotheken über ihre Namensräume, um beispielsweise Referenzen auf andere Bibliotheken und Programme, den Assemblies, herzustellen. Im Beispiel wird eine Referenz auf den Namensraum “System.Windows.Forms” erstellt, mit dessen Assemblies man grafische Benutzeroberflächen erstellen kann. Damit man die Funktionen der Assemblies auch erreicht, müssen sie nach der Referenz noch importiert werden.

Ist der Verweis hergestellt und sind die Assemblies importiert, folgt der Befehl zum Erstellen der MessageBox, der sich nur wenig von dem in VB.NET unterscheidet.

Noch mehr .NET

Natürlich kann man auch selbst geschriebene .NET-Bibliotheken einbinden. In diesem sehr simplen Beispiel soll einmal angenommen werden, dass man eine Bibliothek, die zwei Zahlen miteinander addiert, in einem IronPython-Skript zur Verfügung haben möchte. In VB.NET sieht die entsprechende Klasse folgendermaßen aus:

'File: Add.vb
Namespace myAddName
   Public Class AddClass			
      Shared Function Add(i As Long, _
            j As Long) As Long
            Return (i + j)
      End Function
   End Class
End Namespace

Wichtig ist hier der Namensraum (Namespace), um das Objekt später wieder ansprechen zu können. Dann folgt die Klasse, mit deren Funktion zwei Zahlen miteinander addiert werden. Zum Übersetzen benötigt man einen VB.NET-Compiler, der, sollte er fehlen, zusammen mit dem kostenlosen Visual Studio Express 2010 installiert werden kann. Ist der Compiler vorhanden, übersetzt man den Quellcode mit folgendem Befehl in der Kommandozeile:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc /nologo /target:library /out:myAddLibrary.dll Add.vb

Das Ergebnis ist die Bibliothek bzw. Assembly „myAddLibrary.dll“. In .NET werden übersetzte Programmklassen als ausführbare Programme in sogenannten Assemblies zusammengefasst und bereitgestellt (ähnlich wie Jar-Dateien in Java). Dabei erhält ein Assembly zwar die Endung .exe oder .dll, sie ist aber im Inneren ganz anders strukturiert. Möchte man wissen, ob die DLL-Datei auch richtig funktioniert, kann man sie mit diesem kleinen Programm testen:

'File: Testcode.vb
Imports System
Imports myAddName
Public Class Testcode	
   Shared Sub Main(ByVal args As String())
      args = Environment.GetCommandLineArgs()
      System.Console.WriteLine(AddClass.Add(args(1), args(2)))
   End Sub
End Class

In diesem Programm wird das selbst erstellte Assembly „myAddName“ importiert und anschließend in der Klasse Testcode die aus ihr bekannte Funktion AddClass.Add() ausgeführt. Die beiden Zahlen, die miteinander addiert werden sollen, werden dem Programm Testcode.exe als Argumente übergeben. Das Ergebnis wird schließlich in der Kommandozeile ausgegeben. Beim Kompilieren muss übrigens auch auf die selbst erstellte Bibliothek verwiesen werden, die in das Programm importiert werden soll:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc /nologo /out:TestCode.exe /reference:myAddLibrary.dll TestCode.vb

Anschließend kann man mit TestCode.exe 5 6 in der Kommandozeile schauen, ob alles geklappt hat. Auf das Assembly myAddLibrary.dll kann man mit IronPython zugreifen, indem man mithilfe des Moduls CLR einen Verweis auf die spezielle Datei setzt, so wie man den Verweis auch dem VB.NET-Compiler mitgegeben hat, und die Bibliothek anschließend mithilfe ihres Namensraums importiert:

import clr
clr.AddReferenceToFile("myAddLibrary.dll")
from myAddName import *
AddClass.Add(5, 6)

Die kompletten Arbeitsschritte kann man nochmal anhand der folgenden Abbildung nachvollziehen.

Man muss die IronPython-Befehle nicht der Reihe nach in den Interpreter eingeben, man kann das Ganze auch in ein Skript gießen:

#File: myAdd.py
import clr
clr.AddReferenceToFile("myAddLibrary.dll")
import myAddName 
 
print myAddName.AddClass.Add(5, 6)

Nachdem man das Skript unter den Namen „myAdd.py“ gespeichert hat, kann man es in der Kommandozeile ausführen, indem man ihm den Befehl ipy voranstellt:

ipy myAdd.py

Handelt es sich bei dem Skript um eine Windows- und nicht um eine Konsolen-Anwendung, kann man es auch ohne Konsolen-Fenster ausführen, indem man den Befehl ipyw vor das Skript setzt.

Weitere Bespiele zum Testen und Lernen findet man im Verzeichnis der IronPython-Installation im Ordner „Tutorial“. Noch mehr Beispiele gibt es auch bei Codeplex und Dokumentation mit Beispielen auf der IronPython-Homepage.

Powerscripting

Wenn man anstelle der Kommandozeile cmd.exe die PowerShell benutzt, braucht man nicht den umständlichen Weg über den IronPython-Interpreter zu gehen. Man kann das IronPython-Assembly auch gleich in die PowerShell laden. Voraussetzung dafür ist allerdings, dass die PowerShell .NET 4.0 versteht, was sie in der Standardeinstellung leider nicht kann. Um zu prüfen, welches .NET-Framework die Powershell unterstützt, gibt man folgenden Befehl ein:

PS C:\>[environment]::Version
 
Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      50727  5456

Steht unter „Major“ eine 2, so wie im Beispiel, dann ist der Standard mit .NET 2.0 eingestellt. Da IronPython wie gesagt auf Version 4.0 des Frameworks beruht, legt man im Verzeichnis der PowerShell, „C:\Windows\System32\WindowsPowerShell\v1.0\“, die Konfigurationsdatei „PowerShell.Exe.Config“ mit folgendem Inhalt an:

<?xml version="1.0"?> 
<configuration> 
    <startup useLegacyV2RuntimeActivationPolicy="true"> 
        <supportedRuntime version="v4.0.30319"/> 
        <supportedRuntime version="v2.0.50727"/> 
    </startup> 
</configuration>

Nach einem erneuten Start der PowerShell kann man das IronPython-Assembly laden:

[reflection.assembly]::LoadFrom("C:\Program Files\IronPython 2.7\IronPython.dll")
$ipe = [ironpython.hosting.python]::CreateEngine()
$ipe.Execute("print 'Hallo Welt!'")

Es gehen aber nicht nur einzelne Befehle, mit einem Here-String kann man auch ein ganzes IronPython-Skript in die PowerShell einbetten:

[reflection.assembly]::LoadFrom("C:\Program Files\IronPython 2.7\IronPython.dll")
$ipe = [ironpython.hosting.python]::CreateEngine()
$code = @'
import socket
address = socket.gethostbyname(socket.gethostname())
print address
'@
$ipe.Execute($code)

Das soll nur ein kurzer Einblick sein, welche Möglichkeiten IronPython noch so bietet. Man kann natürlich auch umgekehrt, die PowerShell in IronPython einbetten, oder IronPython zur Skript-Sprache einer selbst erstellten C#-Anwendung machen. Die Grenzen werden dabei nur durch das verwendete .NET-Framework gesetzt.

Fazit

Wer Spaß am Programmieren mit Python hat und sich dazu noch mit dem .NET-Framework von Microsoft beschäftigen will oder muss, für den ist IronPython gerade richtig. Man kann in IronPython mit Windows Forms oder Windows Presentation Foundation (WPF) grafische Benutzeroberflächen entwickeln, die nicht wie Fremdkörper aussehen, oder Bibliotheken in seiner Lieblingssprache Python schreiben und sie mithilfe des IronPython-Compilers in Assemblies übersetzen, die in anderen .NET-Projekten weiter verwendet werden können. Darüber hinaus eignet es sich auch gut zum Testen von Assemblies, da IronPython-Skripte nicht extra kompiliert werden müssen, sondern gleich ausgeführt werden können. Da der Übersetzungsschritt weg fällt, kann man schnell kleine Programme für besondere Aufgaben erstellen. Für .NET-Entwickler hat der Interpreter von IronPython den Vorteil, dass man mit Objekten spielen und sie ausprobieren kann. Ohne sie in ein statisches Programm zu packen und kompilieren zu müssen, kann man Klassen instanziieren und ihre Eigenschaften erforschen. Wer sich tiefer gehend mit IronPython beschäftigen will, muss allerdings gute Englischkenntnisse mitbringen, weil es kaum Dokumentation auf Deutsch gibt. Angefangen mit dem Tutorial, das sich im IronPython-Verzeichnis befindet, über Bücher und Quellen im Internet, die fast alle ausschließlich auf Englisch vorliegen.

IronPython ist noch lange nicht Tod, auch wenn die Entwicklung nach dem Wegfall der aktiven Unterstützung durch Microsoft nur langsam weiter geht und das Projekt auf seinen Begründer Hugunin verzichten muss, nachdem er von Microsoft zu Google gewechselt ist. Im Gegenteil, IronPython zieht bald mit der Python-Version 2.7.3 gleich, die schon als Alpha heruntergeladen werden kann. Außerdem wird in naher Zukunft der letzte große Sprung in der Entwicklung von Python nachvollzogen werden und Versionen 3.2 erscheinen.

Für Open Source-Entwickler ist außerdem das weitere Vorgehen von Microsoft unter Windows 8 und dem .NET-Framework 4.5 interessant, nachdem das Unternehmen angekündigt hat, keinen Compiler mehr mit auszuliefern. Wenn die Unterstützung für Sprachen wie VB.NET, C# oder Visual C++ in den Express-Versionen von Visual Studio 11 weg fällt, werden auf langer Sicht vielleicht Open Source-Alternativen wie IronPython, IronRuby und #Develop als Entwicklungsumgebung interessanter, um Windows- oder Konsolen-Anwendungen zu schreiben. Trotzdem wird IronPython vorerst ein Nischenprodukt bleiben, was einfach in der Natur der Sache liegt: Die Schnittmenge zwischen Python-Programmierern und .NET-Entwicklern ist einfach zu klein.

Geschrieben in freiesMagazin, Python, Windows