Introduction to IronPython

Dynamic Languages on .NET

IronPython in Action

Note

This is a short introduction to both IronPython and IronRuby, new dynamic languages for the .NET framework (and Mono) made possible by the Dynamic Language Runtime (DLR).

This article is the first in a series of articles on developing with IronPython. The other articles are:

A much more complete introduction to programming and embedding IronPython is my book: IronPython in Action.

Introduction

From the foreword to IronPython in Action by Jim Hugunin:

IronPython brings together two of my favorite things, the elegant Python programming language and the powerful .NET platform.

This article will show you how to get started with IronPython and hopefully give you some reasons to be interested in it. Topics we'll cover include:

  • Introduction to IronPython and the dynamic language runtime
  • The interactive interpreter
  • Basic integration with the Common Language Runtime (CLR)

In particular the interactive interpreter is useful for learning about IronPython and for exploring the .NET framework. In this article we'll be using the interactive interpreter to see how IronPython integrates with the .NET framework, and learning a couple of tricks that make it a powerful tool. As well as IronPython we'll see Python's cousin, Ruby, running on .NET and even how IronPython and IronRuby can work together.

Resolver One

When talking about Python and dynamic programming languages to an audience used to statically typed languages like C# I always get asked the same question by someone: Can you maintain large projects in dynamic languages? Is IronPython a real development language or just a toy?

Resolver One - a dynamic language in action

Resolver One is a highly programmable spreadsheet created by Resolver Systems, and the project I have been working on since 2006.

The three founders of Resolver all worked in the London financial services industry. In that business it is very common for people who aren't programmers to need to build business applications. They don't want to have to go the IT department - they need to be able to create applications for very short term opportunities. Currently they're all using Excel. Excel is a great application but beyond a certain level of complexity, the traditional spreadsheet metaphor - of cells in a grid with macros off to one side - breaks down. So the idea for Resolver One was born; a program where the data and formulae in the grid are turned into code (in an interpreted language) and code that the user writes is executed as part of the spreadsheet. This makes it much easier to add your own code and integrate external IT components.

So how did we end up not just using IronPython but writing the whole application in IronPython?

Late 2005 two developers started work on Resolver One. They chose .NET, and Windows Forms as the development platform, a logical choice for a desktop application. And if you're writing a .NET business application, you write it in C# right? That's what the developers assumed.

Having an interpreted language embedded into Resolver is a central part to the way Resolver One works, so they started evaluating scripting language engines available for .NET. At the time IronPython was at version 0.7. What particularly impressed them about IronPython was the quality of the .NET integration. Even more important as a dynamic language it was an order of magnitude easier to test than the languages they had worked with before. This particularly suited the test driven development approach they were using for development. They decided to see how far they could get writing the whole application in IronPython.

That was over three years ago. Resolver One is now written (almost) entirely in IronPython, there's 57 000 lines of IronPython production code, plus around 170 000 lines in the test framework.

You can read more about Resolver One here:

http://www.resolversystems.com/products/resolver-one/

We have a 31-day free trial version, so if you would like to take a look, you can download it from our website:

http://www.resolversystems.com/download/

If you want to use Resolver One in an Open Source project, we offer free licenses for that:

http://www.resolversystems.com/opensource/

How did IronPython come to exist?

Jim Hugunin is the creator of IronPython and was also the original creator of Jython, an implementation of Python for the Java Virtual Machine (JVM). He wrote the following on the origin of IronPython as part of the foreword to IronPython in Action:

I first learned about the CLR by reading countless reports on the web that said it was a terrible platform for dynamic languages in general and for Python in particular. IronPython started life as a series of quick prototypes to help me understand how this platform could be so bad. My plan was to prototype for a couple of weeks and then write a pithy paper titled, “Why the CLR is a terrible platform for dynamic languages.” This plan was turned upside down when the prototypes turned out to run very well—generally quite a bit faster than the standard C-based Python implementation.

Jim turned his initial prototype into a full implementation of Python that he called IronPython. Jim demoed IronPython to Microsoft and was hired by them to work on the CLR architecture team, with the brief of helping to make the Common Language Runtime a better platform for multiple languages including dynamic languages. A separate team, the dynamic languages team, was formed to develop IronPython - which was released under an open source license.

This license IronPython is released under is the OSI approved Microsoft Public License (MS-Pl), which Microsoft now uses for several projects. IronPython was the first project to be released under this license.

The Dynamic Language Runtime

Having created IronPython 1 the Microsoft dynamic languages team recognised that they had created a framework for hosting a dynamic language, complete with type system and compiler support - but it was all tied up in the implementation of a single language. They abstracted out the framework parts of the implementation into the Dynamic Language Runtime and built IronPython version 2 on top of the DLR. They also started an implementation of Ruby for .NET on top of the DLR called IronRuby.

The DLR provides:

  • A framework for creating Dynamic Languages

  • Including interoperation between languages (both statically typed and dynamic)

  • The DLR will be part of C# / .NET 4

  • DLR Languages

    • IronPython (Microsoft)
    • IronRuby (Microsoft)
    • IronScheme ... (Codeplex)
  • A hosting API for use from .NET languages like C# and Visual Basic.NET (VB.NET)

There are also various community languages (IronScheme, Nua, an implementation of Javascript called RemObjects and so on) built on top of the DLR.

Parts of the DLR are becoming part of the .NET framework in .NET 4.0 to support the dynamic keyword in C# 4.0. From our point of view (as users of IronPython rather than language implementors) the most important part of the DLR is the hosting API which is how we embed IronPython or IronRuby in .NET applications and interact with dynamic objects.

What is IronPython?

  • IronPython is a Python compiler
  • An open source implementation of a popular open source programming language
  • Runs on .NET and Mono (in fact included in Mono)
  • Now being developed by a Microsoft team
  • Version 2.6 is built on the Dynamic Language Runtime (targeting compatibility with Python 2.6)
  • Runs on Silverlight

IronPython is a port of the popular programming language Python to the .NET framework. Microsoft are serious about IronPython and dynamic languages for the .NET framework. Microsoft have built IronPython support into various projects.

IronPython is very well integrated with the .NET framework. Strings in Python are .NET string objects, and they have the Python methods that you would expect. The same is true for the other types.

We can also take .NET assemblies and import classes / objects from them, and use them with no wrapping needed

Why Use IronPython?

Some common use cases for IronPython:

  • Dynamically explore assemblies and classes
  • System administration / scripting
  • Prototyping / rapid development
  • User scripting of .NET Applications
  • Business rules stored as text or using a custom Domain Specific Language (DSL)

Of course its also a fine choice for application development. Other Features of IronPython:

  • Trivial to mix / extend with C#, F# and VB.NET
  • Massively easier to test than statically typed languages
  • Runtime introspection (reflection without the pain)
  • You can customise attribute access (good for DSLs)
  • Duck typing
  • Designed for embedding in .NET applications
  • Code can be added or modified without requiring re-compilation (useful for both DSLs and scripting)

The interactive interpreter

The interactive interpreter

The easiest way to start using IronPython is to install it with the msi installer from the Codeplex site. I recommend IronPython 2.6. The installer includes the binaries, the Python standard library, IronPython for Silverlight and a tutorial. It also includes a tool called Pyc.py which can compile IronPython applications into binaries.

Note

Interactive interpreters first appeared in Lisp where they were called the REPL: the Read Evaluate Print Loop.

Installing IronPython does not put ipy.exe on the path. By default it installs into a location like C:\Program Files\IronPython 2.6\ipy.exe. The most convenient way to use it is to add this location to the PATH environment variable. See Basic Hints for Windows Command Line Programming for more details.

ipy.exe is used to execute IronPython programs but doubles up as the interactive interpreter. This is a great tool for experimenting with Python and also for exploring .NET assemblies. The powerful introspection capabilities of Python make it particularly suited for interactive exploration.

Interactive sessions in this documentation will be shown with >>> and ... preceding each line as these are the prompts shown at the console:

>>> from System import Array
>>> help(Array.CreateInstance)
Help on built-in function CreateInstance:

CreateInstance(...)
    Array CreateInstance(Type elementType, Array[int] lengths)

Basic .NET integration

IronPython itself (and the DLR) is written in C#. IronPython uses native .NET types - a string in IronPython is a .NET string, an integer is an Int32 and so on. Access to .NET libraries and classes is provided through the normal Python import machinery.

The first point of contact for interacting with the .NET framework is through the clr module. This has functions for adding references to assemblies, something you would normally do at compile time in Visual Studio. Once we have added a reference to an assembly we can import classes (etc) from the namespaces in the assembly. Here's an example with Windows Forms.

>>> import clr
>>> clr.AddReference('System.Windows.Forms')
>>> from System.Windows.Forms import Application, Button, Form
>>>
>>> form = Form(Text="Hello World")
>>> button = Button(Text="Click Me")
>>> form.Controls.Add(button)
>>>
>>> def onClick(sender, event):
...     print 'Ouch!'
>>> button.Click += onClick
>>> Application.Run(form)
Ouch!
Ouch!
A basic windows forms user interface

We'll be looking at general Python syntax in another article, but there are a couple of points of interest in that short snippet of code.

  1. Note the use of keyword arguments (a standard Python feature) in the constructor of Form and Button for property setting.
  2. The event handler function (onClick) is a standard Python function. Under the hood IronPython will cast it to the right type of delegate that the button click handler requires (EventHandler).

Also note that block structure is indicated in Python with indentation instead of curly braces. The body of the onClick function is indented relative to its declaration.

Note

This example only shows .NET integration in one direction; using the .NET framework from IronPython. Many .NET developers will also be interested in integration in the other direction; using IronPython from C#. This is a more advanced topic as it is done with the Dynamic Language Runtime hosting API. There is a collection of articles and examples showing how to do this at: Embedding IronPython and the DLR.

dir and help

There are two functions that are particularly useful for exploring objects at the interactive interpreter: dir and help.

dir(some_object) returns all the members of an object as a list of strings. Because it is an ordinary Python list you can filter it or mangle it in any way you want. For example here is how we display all the members of the System namespace who's names start with 'I':

>>> import System
>>> for member in dir(System):
...     if member.startswith('I'):
...         print member
...
IAppDomainSetup
IAsyncResult
ICloneable
IComparable
IConvertible
ICustomFormatter
IDisposable
IEquatable
IFormatProvider
IFormattable
(and so on...)
>>>

help(some_object) gives us a bit more information about an object. Text printed out by help either comes from XML documentation for .NET libraries or from docstrings for Python objects. Calling help on a class will print out information on all the methods, you can also call help on individual methods:

The help function
>>> from collections import namedtuple
>>> help(namedtuple)
Help on function namedtuple in module collections:

namedtuple(typename, field_names, verbose=False)
    Returns a new subclass of tuple with named fields.

    >>> Point = namedtuple('Point', 'x y')
    >>> Point.__doc__                   # docstring for the new class
    'Point(x, y)'
    >>> p = Point(11, y=22)             # instantiate with positional args or keywords
    >>> p[0] + p[1]                     # indexable like a plain tuple
    33
    >>> x, y = p                        # unpack like a regular tuple

The collections module is part of the Python standard library. namedtuple is a class factory; you use it to create new classes that behave like enumerations (which Python doesn't have as a built-in type):

>>> from collections import namedtuple
>>> Point = namedtuple('Point', 'x y')
>>> point = Point(1, 3)
>>> point
Point(x=1, y=3)
>>> point.x
1
>>> point.y
3

The ability to create new classes at runtime is one of the advantages of dynamic languages.

Setting sys.path

An important factor when working from the interactive interpreter is where Python looks when we execute an import statement or attempt to add a reference to an assembly. By default all the standard .NET frameworks are available to add references to. In addition the IronPython installer includes the Python standard library. For anything else we need to tell IronPython where to look for Python modules and assemblies.

The mechanism that Python uses for looking for Python modules is a Python list in the sys module called sys.path. IronPython also uses sys.path to tell it where to look for assemblies when you attempt to add a reference to one. To add a new directory to the search path we simply append the path as a string:

>>> import sys
>>> path = 'c:\\Projects\\MyProject'
>>> sys.path.append(path)
>>> import clr
>>> clr.AddReference('MyAssembly')

Because the backslash acts as an escape character in strings we have to double up backslashes in paths.

IronRuby

IronRuby is the 'other' major dynamic language for .NET, implemented by Microsoft using the Dynamic Language Runtime.

IronRuby interactive interpreter

IronRuby also has an interactive interpreter: ir.exe. You can download it from www.ironruby.net:

>> require 'System.Windows.Forms'
>> Forms = System::Windows::Forms
>> form = Forms::Form.new
>> form.Text = 'Hello World'
>> button = Forms::Button.new
>> button.Text = 'Click Me'
>> form.Controls.Add(button)
>> button.click {|sender, event| puts 'Ouch!'}
>> Forms::Application.run form

Ruby is, in many ways, a very similar language to Python. An interesting comparison Python vs Ruby, slightly more in-depth concludes: "These languages are interchangeable".

There are many differences though and in general Python is more similar to C# and VB.NET than Ruby is; both in terms of syntax and object model.

IronPython together with IronRuby

Through the Dynamic Language Runtime IronPython and IronRuby can even interoperate, sharing classes and libraries. When a Ruby object is used from Python it retains its semantics as a Ruby object and vice-versa:

from System import Array

paths = [r'C:\IronRuby\lib\IronRuby', r'C:\IronRuby\lib\ruby\1.8']
array = Array[str](paths)

source_code = "require 'date'"

from IronRuby import Ruby
engine = Ruby.CreateEngine()
engine.SetSearchPaths(array)
source = engine.CreateScriptSourceFromString(source_code)
source.Execute()

RubyDate = engine.Runtime.Globals.Date

date = RubyDate(2009, 9, 22)
print date.year()

The classes used to host the Ruby engine in IronPython here are part of the DLR hosting API, which are covered in more detail in Embedding IronPython and the DLR.

Python

The Python Programming Language

Python is a dynamically typed, cross-platform, Open Source, object-oriented, high-level programming language. Python was first released publicly in 1991 making it older than C#. Python is widely used in many different fields:

  • Linux system administration
  • Standard scripting language for GIS & Animation
  • Web development (Google, Youtube, Django)
  • Games (Civilization IV, Eve Online)
  • Science (especially genetics and linguistics)
  • Applications, industry etc...

Python is a great general purpose language and so gets used for a wide variety of things. It grew out of the Unix culture, which is reflected in some of its major uses. Here are a few examples:

Python is used for web development:

  • Youtube is written almost entirely in Python on the server
  • Python is one of google's '4 approved languages'. To quote Alex Martelli (a senior google developer), they use 'Python where we can, C++ where we must'
  • Trac - the popular online project management app. is written in Python

Games:

  • The massively multiplayer online game EVE is almost entirely written in Python on the server side
  • Civilization IV is scriptable in Python, and the developers liked it so much that large chunks of the game ended up written in Python as well

Animation and CGI:

  • Most of Sony Imageworks' animation pipeline is written in Python. It is also used by Pixar and Industrial Light and Magic.
  • Python is the embedded scripting language for applications like Blender and Maya.

Python has become the 'scripting language of choice' for several major Geographical Information Services (GIS) applications and some of these are starting to use IronPython.

In recent years Python has virtually replaced Perl as the standard Linux system admin language:

  • Gentoo and Fedora package management (Yum and Portage) are written in Python
  • Ubuntu and Pardus Linux distributions do everything they can in Python

Desktop applications: the original BitTorrent was (and is) written in Python. Python has been used to implement two major distributed source code control systems: Bazaar and Mercurial.

IronPython is now used internally in Microsoft, for example Microsoft Knowledge Tools.

Python gets used a lot in London banking (along with C#, making finance another area that IronPython is gaining ground).

Python gets used a lot in science, both because it is an easy language for scientists to learn and it has bindings to a wide range of numerical and scientific processing libraries written in C and Fortran (e.g. BioPython, Numpy and SciPy). It is particularly used for genetic research (because of its powerful string handling capabilities) and linguistic analysis (because of an especially powerful toolkit called the Natural Language Toolkit).

Python gets used in industry, for example Seagate automate their hard drive testing with Python. Libraries like PySerial and PyParallel make it easy to control external devices, so Python is being used to control robots. There is even an implementation for embedded systems called Python on a chip.

The Zen of Python

Try import this in an interactive interpreter. This is an expression of the Python philosophy originally written by Tim Peters. Tim was one of the early developers of Python and is the creator of the awesome fast sort algorithm used by Python lists which is now known as 'timsort'.

The Zen of Python

'timsort' is being considered for use by Java as the default sort implementation. It takes advantage of partial sorting in lists, making much faster on average and no slower in the worst case, and uses less memory than the current implementation in Java.

The next image is by Guido van Rossum, from a presentation to Hewlett Packard, on the principle that has guided the development of Python syntax and language features. The emphasis is on clear and readable code.

Python and readability

To a Python programmer telling them that their code is clever is more likely to be taken as an insult than a compliment!

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."

—Brian Kernigan

Where Next?

There are plenty of other places to turn for more information on IronPython. The next article in this series is Python for .NET Programmers.

Here are a few other suggestions:

For buying techie books, science fiction, computer hardware or the latest gadgets: visit The Voidspace Amazon Store.

Hosted by Webfaction

Return to Top

Page rendered with rest2web the Site Builder

Last edited Fri Nov 27 18:32:35 2009.

Counter...