NET + Python = Ironpython
Total Page:16
File Type:pdf, Size:1020Kb
Programowanie .NET Janusz Gołdasz Iwona Gołdasz .NET + Python = IronPython laczego ktoś mógłby chcieć korzystać z Py- thona na platformie .NET? Z jakich mecha- D nizmów (narzędziach) dostępnych w świecie .NET może programista Pythona skorzystać? Odpo- wiedź jest jedna: możliwość wyboru. Wybór języka pro- gramowania sprowadza się często do indywidualnych preferencji i cech/typu projektu, nad którym pracujemy. Python w przedstawianej implementacji jest inte- resującym rozwiązaniem na platformy .NET i Mono (fanom Javy polecamy Jythona) i wydaje się, iż ma Rysunek 1. Odtworzony dokument XML wszelkie dane ku temu, aby przyciągnąć do siebie nowych zwolenników. Skryptowy Python, stworzony gnięcia IronPythona do grafiki 3D na przykładzie biblio- we wczesnych latach 90-tych przez Guido van Rosu- teki Irrlicht .NET 3D. Zakładamy opanowanie przez czy- uma, jest dziś wykorzystywany praktycznie na każ- telnika podstaw programowania w Pythonie i .NET. Ko- dej powszechnej platformie (Windows, Max, Lunux/ niecznie trzeba zwrócić uwagę, iż IronPython i CPython Unix) od komputerów stacjonarnych po palmtopy i te- to dwie różne implementacje tego samego języka. Róż- lefony komórkowe (Nokia) w takich dziedzinach jak, nic w chwili obecnej jest sporo – od bardzo trywialnych, wizualizacja i gry, networking, aplikacje webowe, de- które sprowadzają się do wyświetlania różnych komuni- sktopowe, inżynieryjne, bazy danych, etc. Jest uży- katów o błędach, po takie, które wynikają z nieobecno- wany do tworzenia prostych skryptów, jak i dużych ści takiego czy innego modułu, np. cmath lub os. aplikacji (Zope, Plone). Poniżej postaramy się przed- stawić jego implementację na platformę .NET. Narzędzia Standardowo, IronPython (binaria i kody źródłowe do IronPython pobrania z CodePlex) daje użytkownikowi zestaw po- Twórca IronPythona, Jim Hugunin, jest znany z wcze- dobnych narzędzi programistycznych co inne imple- śniejszych (udanych) implementacji Pythona na maszy- mentacje tego języka (CPython). Do dyspozycji jest nę wirtualną Javy – Jython. Projekt na platformę .NET konsola interpretera poleceń (ipy.exe), a uruchamianie powstał około roku 2003 i jest przykładem świetnej skryptów i poleceń IronPythona odbywa się w znanych i szybkiej implementacji dynamicznego języka skrypto- nam postaciach: wsadowo lub interaktywnie. W chwi- wego w środowisku CLR (platformy .NET i Mono). Inte- li obecnej, jedyne środowisko programistyczne (IDE) resujące jest oparcie się przez twórców na środowisku pozwalające tworzyć/edytować skrypty w tym języku CLR, co w rezultacie zapewnia wykorzystywanie biblio- to Visual Studio 2005 koniecznie w wersji Standard lub tek .NET w tworzonych skryptach, aplikacjach desktopo- wyższej. W chwili obecnej brak wsparcia dla IronPytho- wych i webowych przy użyciu IronPythona. Co ciekawe, na w wersji Visual Studio Express, choć istnieje ono przy zachowaniu pewnych reguł, możliwe jest korzysta- w Web Developer Express (po zainstalowaniu dodatko- nie ze standardowych bibliotek CPythona celem zwięk- wego pakietu integrującego IronPythona z ASP .NET). szania funkcjonalności tworzonej aplikacji o potrzebne Do tworzenia przykładów zawartych w niniejszym ar- elementy. Współpracę IronPythona z .NET pokażemy tykule autorzy korzystali z Visual Studio Express (C#) na kilku wybranych przykładach. Zaczniemy od napisa- oraz popularnego IDLE (Python). nia skryptu w Pythonie w rodzaju prostej przeglądarki pli- ków XML z wykorzystaniem kontrolki TreeView i formula- Skrypty rza Form. Tworzenie nowych rozszerzeń (klas) w C# dla Omówienie IronPythona rozpoczniemy od skryptu, któ- IronPythona pokażemy na przykładzie podobnej aplika- rego działanie polegać ma na odczytaniu pliku XML, cji, gdzie komponent przeglądarki osadzimy tym razem a następnie odtworzeniu jego struktury w kontrolce w wyświetlanym formularzu. Korzystanie z interprete- TreeView jak na Rysunku 1. Treść skryptu przedstawio- ra IronPythona przedstawimy na przykładzie aplikacji – no w Listingu 1. Rozpoczynamy od zapewnienia sobie słownika. Na koniec, omówimy prosty przykład zaprzę- dostępu do standardowych modułów CPythona. Robi- my to przez umieszczenie na początku skryptu nastę- Autorzy są entuzjastami Pythona we wszystkich wcie- pujących wierszy leniach (czytaj: implementacjach). Kontakt: [email protected] import sys sys.path.append(r"c:\python24\lib") 30 www.sdjournal.org Software Developer’s Journal 02/2007 .NET + Python = IronPython Oczywiście, importujemy moduł clr (CLR), a dostęp do potrzeb- danie odtworzenia struktury dokumentu XML się kończy. Chcąc nych modułów .NET zapewniamy sobie dzięki metodzie clr.Ad- umieścić (wyświetlić) naszą kontrolkę w formularzu, w konstruk- dReferenceByPartialName(...). W naszym skrypcie utworzy- torze klasy HelloXML tworzymy instancję klasy xmlTree i wywołu- my 2 klasy – pierwszą o nazwie xmlTree dziedziczącej po kla- jemy metodę PopulateTree(), Teraz wystarczy tylko dodać ją do sie TreeView, drugą zaś (dziedziczącą po klasie Form) nazwie- formularza i w funkcji Main umieścić znaną skądinąd my HelloXML. Klasa xmlTree posiada 2 zmienne: pathToXML (w której przechowywać będziemy ścieżkę do analizowanego pli- Application.Run(HelloXML(nazwa_pliku_XML)) ku) oraz root, która posłużymy się do przechowania treści doku- mentu (XmlDocument). Odtworzenie struktury dokumentu XML i efekt jest widoczny jak przedstawionej ilustracji w Rysunku 1. najłatwiej rozwiązać rekurencyjnie – stąd obecność w ciele kla- Chcąc sprowokować pojawienie się wyjątku, wywołamy skrypt sy kolejnych metod. Pierwsza z nich o nazwie AddNode(...) po- z nazwą nieistniejącego dokumentu – zob. Rysunek 2. rusza się rekurencyjnie po strukturze (drzewiastej) analizowane- go dokumentu, dodając odwiedzane węzły inXMLNode do kolej- Tworzenie rozszerzeń nych węzłów inTreeNode naszej kontrolki. Druga metoda Popula- Tworzenie rozszerzeń .NET dla IronPythona pokażemy na iden- teTree() to sterownik wczytujący żądany dokument do zmiennej tycznym przykładzie jak poprzednio – zob. Listing 2. Nasze za- root i wywołujący rekurencyjną metodę AddNode(...). Na tym za- danie polega na osiągnięciu identycznej funkcjonalności jak Listing 1. Pierwszy przykład - xmlTree import sys self.Nodes.Add(TreeNode(System.Convert.ToString( # Dodajemy dostep do standardowych modulow Pythona detail))) sys.path.append(r"c:\python24\lib") # Zadaniem rekurencyjnej metody AddNode jest dodawanie # Importujemy Common Language Runtime … # kolejnych wezlow do kontrolki import clr def AddNode(self, inXmlNode, inTreeNode): # Formularze, kontrolki tNode = TreeNode() clr.AddReferenceByPartialName("System.Windows.Forms") i = 0 clr.AddReferenceByPartialName("System.Drawing") # Gdy rodzic inXmlNode posiada dzieci, # XML # to rekurencyjnie wedrujemy po drzewku clr.AddReferenceByPartialName("System.Xml") if (inXmlNode.HasChildNodes): # ...oraz inne potrzebne moduły for node in inXmlNode.ChildNodes: import System xNode = inXmlNode.ChildNodes[i] from System.Windows.Forms import * inTreeNode.Nodes.Add(TreeNode(xNode.Name)) from System.Drawing import * tNode = inTreeNode.Nodes[i] from System.Xml import * self.AddNode(xNode, tNode) # Tworzymy kontrolke przegladarki i+=1 # – dziedziczy po klasie TreeView else: class xmlTree(TreeView): inTreeNode.Text = (inXmlNode.OuterXml) def __init__(self): # Domyslny bezparametrowy konstruktor # Klasa HelloXML dziedziczy po klasie Form self.Nodes.Clear() class HelloXML(Form): self.pathToXml = '' # Sciezka do pliku XML # Konstruktor z parametrem w postaci nazwy pliku XML self.root = None def __init__(self, filename): # W metodzie PopulateTree generujemy structure pliku XML self.xmlTree = xmlTree() # Instancja klasy xmlTree ! def PopulateTree(self): self.xmlTree.pathToXml = filename self.root = XmlDocument() # korzen # Zapelniamy drzewko kontrolki … try: # obsluga wyjatkow self.xmlTree.PopulateTree() self.root.Load(self.pathToXml) # Otwieramy plik self.xmlTree.Dock = DockStyle.Fill # Kasujemy wszystkie istniejace wezly # … i dodajemy je do formularza self.Nodes.Clear() self.Controls.Add(self.xmlTree) # Dodajemy pierwszy wezel (korzen) do drzewa self.Size = Size(300,200) self.Nodes.Add(TreeNode(self.root. self.AutoSizeMode= AutoSizeMode.GrowAndShrink DocumentElement.Name)) # Tu metoda Main jest na zewnatrz klasy tNode = TreeNode() def Main(filename): tNode = self.Nodes[0] # Wskazanie na korzen Application.Run(HelloXML(filename)) # i rekurencyjnie zapelniamy cale drzewo # Na koniec: uruchamiamy skrypt z parametrem z postaci pliku self.AddNode(self.root.DocumentElement, tNode) # XML i wywolujemy metode Main except Exception, detail: if __name__=="__main__": # Komunikujemy blad import sys MessageBox.Show(System.Convert.ToString(detail)) Main(sys.argv[1]) self.Nodes.Clear() Software Developer’s Journal 02/2007 www.sdjournal.org 31 Programowanie .NET w poprzednim przykładzie. Tym razem jednak, rozpoczniemy struktury pliku XML (pośrednio, poprzez wywołanie w treści wła- od utworzenia kontrolki przeglądarki i wywołania jej w nowym ściwości metody PopulateTree()). skrypcie. Zaczynamy od utworzenia nowego projektu typu Class Tak utworzoną kontrolkę możemy bezproblemowo użyć Library w Visual Studio i utworzenia nowej klasy o nazwie (nie- w naszym skrypcie, co przedstawia Listing 3. Oprócz oma- spodzianka!) xmlTree. Oczywiście, klasa ta powinna dziedziczyć wianej już zawartości w skrypcie pojawia się referencja do po klasie TreeView. W ciele klasy pojawiają się konstruktor z pa- nowej kontrolki przy użyciu metody AddReferenceToFi- rametrem w postaci nazwy pliku XML, którego strukturę odtwa- le modułu clr. i import klasy xmlTree do naszego