Monday, August 17, 2009

Command Line Options and Configuring Your Engine

The blog entry I'm focusing on here is in Russian. Normally this means I would mention it one of the "good mix" posts but not spend too much time on it, however it makes a useful point that I think is worth explaining:
First of all the author recommends Eclipse 3.5, along with PyDev 1.4.7 and IronPython 2.6 Beta 2 - which in itself is an interesting combination for IronPython development. (Ironic that the big Java IDE has much better support for IronPython than the big .NET IDE.)

One of the new things in IronPython 2.6, and in fact the reason that PyDev is able to have support for things like debugging IronPython code, is support for Python stack frames and APIs like sys._getframe, sys.settrace and so on.

To run IronPython with this enabled you need to use a magic command line switch, of which IronPython has many. You can get a list of them by running ipy.exe -?:

None of the ones above are standard to Python, although some of them would be nice. Useful for the command line are: -X:AutoIndent -X:ColorfulConsole -X:TabCompletion. For access to private .NET members you pass -X:PrivateBinding, for longer CLR exception tracebacks use -X:ExceptionDetail and -X:ShowClrExceptions and to run IronPython in an MTA thread (Multi Threaded Apartment - the default is STA) use -X:MTA.

To enable stack frames you have the choice of -X:Frames and -X:FullFrames. The difference is as follows:
-X:FullFrames promotes all local variables into the heap. So you can always crawl the stack and look/change them for all methods.

-X:Frames only creates the frame objects and if something happens to make us promote local variables (e.g. a closure, or a call to locals(), exec, eval, dir(), vars()) then the local variables will be available for that specific method.
Another useful switch is to enable the profiler built into IronPython 2.6: -X:EnableProfiler. Curt Hagenlocher (core IronPython developer) described the profiler in a blog post a while ago: An IronPython Profiler.

An important question, and the one answered by the Russian blog post, is how do we enable all these features when embedding IronPython instead of launching it from the command line. Fortunately the answer is simple. Create a .NET Dictionary to store options in, and set entries using the same name as the command line switch (the part after the -X:) as the key. Set the value in the dictionary to ScriptingRuntimeHelpers.True.

So, here is the snippet of C# to create a Python engine with the profiler switched on:
var options = new Dictionary();
options["EnableProfiler"] = ScriptingRuntimeHelpers.True;

var engine = Python.CreateEngine(options);
ScriptingRuntimeHelpers lives in the Microsoft.Scripting.Runtime namespace so you will need the appropriate using statement.

To switch frames on as well add this line before creating the engine:
options["FullFrames"] = ScriptingRuntimeHelpers.True;
Easy hey!


  1. Hello Michael,

    Thanks for the info. I have a problem that is similar. I want to use your Plugin example from chapter 15.3 to execute python code on the fly. But I want to execute Microsoft Robotics Studio Python code. This requires ipy.exe to be executed from the MRDS bin folder exclusively. So I need to execute the following command line script through C#:

    MRDS\foobarpath\bin\ipy.exe -X:TabCompletion -i ""

    where is the passed in python file in C#

    Any idea how this can be accomplished?



  2. I don't think you'll be able to (easily) start a script in interactive mode (-i command line option) from inside C#. The interactive console uses stdout and stdin - you could look at how ipy.exe implements this if you are determined.

  3. Thanks for the response. Actually the -i command line option is not necessary. It will still work without it. The problem I am having is trying to execute ipy.exe from inside the MRDS bin folder through C# (I copied ipy.exe into the MRDS bin folder). I am not sure if this can be set by passing a Dictionary object to the Python engine or through some other method.


  4. Now I have no idea what you are trying to achieve. If you want to launch ipy.exe as an external process then you don't *need* an IronPython engine and can just use System.Diagnostics.Process.

    If you just want to execute Python code then you don't need ipy.exe and should use the IronPython engine directly from your C#. :-)

  5. Thanks for the input.

    Actually a combination of both worked out well for me.



Note: only a member of this blog may post a comment.