People who know me know that Python has always been one of my favorite languages. And over the years, I've been pleased with the array of development tools that have been created for it, including the different IDEs.
I also do a lot of work in .NET, primarily with C#. And although I once wrote a raving review of the .NET implementation of python called IronPython, truth be told, I never use IronPython anymore. Not at all. In the past, oh maybe four years, I've created a grand total of two IronPython programs, each consisting of maybe three lines of code, just to try it out. As such, I've had little use for the IronPython tools for Visual Studio, which is a tool that lets you develop and debug IronPython code from within Visual Studio. Instead, when I use python, it's the original python, called CPython (because it's written in C), that I use. And when I want to target .NET, I use C#.
And so while the IronPython tools for Visual Studio have sat idle on my computer, I'm certainly open to a new tool put out by a team at Microsoft called Python Tools for Visual Studio. Why? Because it supports CPython, not just IronPython. The tool is free and open source, and it works in any of the non-free versions of Visual Studio, or with the free, standalone Visual Studio Shell. Let's take it for a test drive.
Trying Out Python Tools For Visual Studio
First, in case you're wondering, this tool replaces the previous IronPython tool for Visual Studio. I'm not really sure if this is a competing tool to the main IronPython tool, or if this is the next generation. I wasn't able to find out at the time of this writing. But if I do find out later (and DaniWeb readers even care), I'll post the answer in the comments. But some of you might remember something that happened almost a year ago: Microsoft suddenly stopped supporting IronPython. Shortly after that, the original creator of IronPython left his job at Microsoft. IronPython continued to live on as a community-supported, open-source project within the Microsoft's CodePlex open source site. But it was unclear what Microsoft was doing; a lot of people were surprised because there had been growing interest in a version of python that targets .NET (even though I wasn't interested). And so for Microsoft to release an updated set of tools for IronPython is a bit perplexing. I'm not sure if they've changed their mind about Python, or what. (The beta of these new tools was announced back in March, so this isn't a sudden surprise. But it's still a bit unclear what Microsoft's intentions are.) And to make it even more confusing, Microsoft's open source development site, CodePlex, hosts both IronPython and these new tools.
Anyway, because IronPython has been available for a long time and isn't new here, I'm going to focus this review on the CPython aspect of this new tool.
Installation is easy, as long as you first uninstall any previous IronPython tool you have installed into Visual Studio. Then after installation, you get a few new project types. They're all grouped together as Python, rather than IronPython, and your choices are IronPython WinForms Application, Python Application, IronPython Application, IronPython Silverlight Application, and IronPython WPF Application. The project type I'm going to focus on is the Python application.
When you create a new Python application, you get a project in Visual Studio containing your python code. Although this is a Visual Studio project, it's a true python application. However, in order for the new program to run under python, you need to configure Visual Studio to find your python interpreter. (Initially when I tried it, it located IronPython, which isn't what I wanted.) To set the interpreter, you click the Tools Menu -> Options, and in the Options dialog box, find the Python Tools settings. There's an Interpreter Settings option, where you can add a new interpreter, and have it point to the python.exe file.
Initially when you create a project, you get a single file with a single line of code:
From there you can create a python program just as you normally would.Debugging
The first thing I wanted to test out was the debugger. Years ago I wrote my own python debugger, and I was aware of what it involved. And understanding the architecture, I was curious how well this tied into the python debugging system. So I added a few more lines of code:
I then set a breakpoint on the final line, and pressed F5, which launches the Visual Studio debugger. Here's what I saw:
Sure enough, the debugger stopped at the line with the breakpoint. And look closely at the top of the console window: The executable is the actual CPython executable, python.exe. So I really am running a python program, not just an IronPython program.
The usual debugging features work, too. As I float my mouse over my x dictionary variable, I saw its values in a popup:
I was also able to modify the values in the little inspection popup by clicking on the values and then changing them.
The watch window works too:
However, I wasn't able to modify variables in the watch window. I'm not sure why they let me do it in the popup inspector but not in the watch window.
The other debugging windows work too; for example, the Call Stack window works, as does the Locals window. The Locals window, in fact, shows me everything that's local to the stack frame, just like what you would see if you typed dir() at the python command prompt. Look at the similarities. First, here's the Locals window:
And here I'm running python.exe manually and entering the same code, followed by a call to dir():
(There's no __file__ member because I've entered the code interactively.)Intellisense
One feature I've always appreciated about Visual Studio is its Intellisense feature, where it can show you object member names, for example. And that feature works with python. Look at this screenshot:
I'm creating a class, and Visual Studio quickly parses it as I type it. By the time I type
Visual Studio supplies the members that it found in the class. But just how smart is it? Let's find out. Python is a dynamic language, and you can add members to variables on the fly. Look closely at this code:
When the first print line runs, the class has members a and b, but the member c doesn't yet exist. So if I had instead typed this:
this.a = 'Hello'
this.b = 'Goodbye'
print this.c # -- Trying to access member c, but it doesn't exist yet --
this.c = 'Everyone'
I'll get a runtime error:
Traceback (most recent call last):
line 10, in <module>
q = MyClass()
line 5, in __init__
AttributeError: MyClass instance has no attribute 'c'
Press any key to continue . . .
But alas, Intellisense doesn't know that:
Technically, on the first print line, Intellisense should only offer a and b as members, not c. Only after the line this.c = 'Everyone' should Intellisense offer c as an option. So it's not perfect.
The Intellisense is smart enough, however, to pick up the members of a class. So if I add a foo function to my class, Intellisense will know about it, as you can see here:
Then when I type foo and an open parentheses, Intellisense shows me the parameters. And it's even smart enough to recognize that the first parameter in a class function is the this parameter, and so it leaves that parameter off (since you don't type it in the arguments list; it's implied):
Finally, I wanted to test one more thing with Intellisense, and it failed. See if you can see the problem here:
What class is q when I typed the dot? It's MySecondClass, which doesn't have a foo member. It has a member called something. But the popup shows foo, not something.
Still, other than these few quirks, I did find that Intellisense worked quite well.Other Features
There are a lot of other nice features. For example, you can right-click on a function name, and in the popup menu click Go To Definition. The editor will take you to the place where the function is declared.
You can also rename identifiers and have the IDE fix all the references to the name for you. Before even trying it out, I suspected that it's not perfect, considering the problem I had earlier of effectively redeclaring a variable.
To rename a variable, you can obviously just type over it with a new name, but that doesn't rename all the instances (unlike in C# where you get an option afterwards to rename them all). Instead, to rename the variable, right-click it, click Refactor -> Rename… and change the name in the message box that opens. You'll then get a dialog box letting you preview the changes:
This works for the most part, even if you have two separate classes that both have a function with the same name. The refactoring will correctly ignore the second class's function if you're changing the first class's function. But you can still fake it out if you do like I did earlier and create an instance of the first class, save it in a variable, then create an instance of the second class and save it back in the same variable. But unless you do crazy things like that, the refactoring will work well.Summary
I'm definitely impressed with Python Tools for Visual Studio. I don't know if I'll start using it as my main python IDE or not. I'll certainly use it for awhile and see how I feel in the long run.
ever since I've stumbled across Python Tools a while ago, I've never set it down :)
I even had to rate the implementation to be better than Eclipse. :)
I've tried Aptana, which has alot of cool and convenient code-completion features, but no smart popups, and forced the use of "self" in classes or returned a warning.
(I personally prefer "this" as compaired to JS, as it just makes sense) :P
I prefer Python 2.7 because PyOpenGL's implementation is less restricted than Python 3x, making it run faster, and PT has no problem with it. :)
I've never used IronPython as my very first module didn't even work with it...
that aside, since then, I've grown to hate .NET and have moved on to cross-compatibility.
Here is an example of a typical IronPython code ...
Ironpython code to load a list with filenames of a given directory
click on a list line to select the filename
IronPython gives access to the Windows .NET or Linux Mono libraries
download and install
or latest version from:
Design with SharpDevelop IDE and save to a file
then bring file into Komodo IDE and use
to get rid of the confusing tabs
tested with Ironpython 2.7.4 by vegaseat
# add these five lines in Komodo IDE
# created with the SharDevelop4 IDE Formbuilder
from System.Drawing import *
from System.Windows.Forms import *
self._button1 = System.Windows.Forms.Button()
self._listBox1 = System.Windows.Forms.ListBox()
self._textBox1 = System.Windows.Forms.TextBox()
self._label1 = System.Windows.Forms.Label()
self._label2 = System.Windows.Forms.Label()
self._button1.Location = System.Drawing.Point(259, 13)
self._button1.Name = "button1"
self._button1.Size = System.Drawing.Size(119, 23)
self._button1.TabIndex = 0
self._button1.Text = "Load Filenames"
self._button1.UseVisualStyleBackColor = True
self._button1.Click += self.Button1Click
self._listBox1.BackColor = System.Drawing.Color.Yellow
self._listBox1.FormattingEnabled = True
self._listBox1.Location = System.Drawing.Point(12, 54)
self._listBox1.Name = "listBox1"
self._listBox1.Size = System.Drawing.Size(366, 342)
self._listBox1.TabIndex = 1
self._listBox1.SelectedIndexChanged += self.ListBox1SelectedIndexChanged
self._textBox1.Location = System.Drawing.Point(103, 15)
self._textBox1.Name = "textBox1"
self._textBox1.Size = System.Drawing.Size(139, 20)
self._textBox1.TabIndex = 2
self._label1.Location = System.Drawing.Point(12, 15)
self._label1.Name = "label1"
self._label1.Size = System.Drawing.Size(85, 18)
self._label1.TabIndex = 3
self._label1.Text = "Enter Directory:"
self._label2.Location = System.Drawing.Point(19, 413)
self._label2.Name = "label2"
self._label2.Size = System.Drawing.Size(150, 25)
self._label2.TabIndex = 4
self._label2.Text = "label2"
self.ClientSize = System.Drawing.Size(442, 447)
self.Name = "Form1"
self.Text = "Form1"
def Button1Click(self, sender, e):
directory = self._textBox1.Text
# if no directory given, pick a default directory
if not directory:
directory = "C:/IronPython2.7/Atest_ip27"
self._textBox1.Text = directory
# make it the working directory
#print(os.getcwd()) # test
# create a list of all files in a given directory
file_list = 
#mask = "*.jpg" # .jpg files only
mask = "*.*" # all files
for path in glob.glob(mask):
dirname, filename = os.path.split(path)
#print(filename) # test
#print(file_list) # test
def ListBox1SelectedIndexChanged(self, sender, e):
"""get the selected listbox item"""
# put the selected item text into a label
if self._listBox1.SelectedIndex != -1:
self._label2.Text = self._listBox1.SelectedItems.ToString()
# final line added in Komodo IDE to make this run
Run the code above in the Komodo IDE with this run line ...
C:/IronPython2.7/ipy.exe -u %F