Review of Python Tools for Visual Studio

jeffcogswell 3 Tallied Votes 2K Views Share
Manufacturer
Microsoft
Price
Free
Pros
Includes regular python (
Cons
There are a few quirks in the Intellisense
Summary
Overall Python Tools for Visual Studio works very well. The quirks are few and rare, and it should work quite well for serious python developers.
Rating

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:

print('Hello World')


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:

print('Hello World')
x = {}
x['a'] = 'b'
x['b'] = 'c'
print(x['a'])

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():

c:\dev\languages\Python26 >python
>>> x = {}
>>> x['a'] = 'b'
>>> x['b'] = 'c'
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'x']
>>>


(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

print this.


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:

class MyClass:
    def __init__(this):
        this.a = 'Hello'
        this.b = 'Goodbye'
        print this.a
        this.c = 'Everyone'
        print this.c


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:

class MyClass:
    def __init__(this):
        this.a = 'Hello'
        this.b = 'Goodbye'
        print this.c  # -- Trying to access member c, but it doesn't exist yet --
        this.c = 'Everyone'
        print this.c


I'll get a runtime error:

Traceback (most recent call last):
  File "c:\dev\tests\IronPython\IronPythonTests3\PythonApplication1\Program.py",
 line 10, in <module>
    q = MyClass()
  File "c:\dev\tests\IronPython\IronPythonTests3\PythonApplication1\Program.py",
 line 5, in __init__
    print this.c
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.

Also, I wasn't able to cover all the features here in this short article; if you want to see more, you can head over to the documentation for the tool on the CodePlex site, here .

Gribouillis commented: very nice review +13
Dan08 8 Junior Poster

This is nice, nonetheless it wouldn't work for a person like me that does all sort of programming in a Linux box.

Tcll 66 Posting Whiz in Training Featured Poster

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.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

The lack of communication between Microsoft's different departments seems to be obvious.

It is my distinct feeling that Microsoft never liked Python, so they put it in Irons.

Years ago Microsoft tried to take over Java, this might have been an attempt to take over Python.

Tcll 66 Posting Whiz in Training Featured Poster

am I right in assuming IronPython is Win only, or can it work w/o .NET??

OT: if I'm right, I think that's the reason MS don't like Python. XD
MS: oh it works on other OS's besides Windows? we already don't like it.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

If you like C#, then IronPython isn't that bad.

Tcll 66 Posting Whiz in Training Featured Poster

well C# is a .NET language :P
(I think C# was actually based on .NET)

would be nice if MS would port .NET to Linux and Mac.

MS: oh no, we wouldn't do that... eh heh...
it'd give our users too much freedom, and especially rules out our control over them.

I want MS to prove me wrong on that... heh

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

There is a NET version for Linux called Mono.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Here is an example of a typical IronPython code ...

''' ip_file_list1.py
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
IronPython-2.7.4.msi
or latest version from:
http://ironpython.codeplex.com/

Design with SharpDevelop IDE and save to a file
then bring file into Komodo IDE and use
Edit/Select/'Select All',
then use
Code/'Untabify Region'
to get rid of the confusing tabs

tested with Ironpython 2.7.4 by vegaseat
'''

# add these five lines in Komodo IDE
import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")
import glob
import os


# created with the SharDevelop4 IDE Formbuilder
import System.Drawing
import System.Windows.Forms

from System.Drawing import *
from System.Windows.Forms import *

class Form1(Form):
    def __init__(self):
        self.InitializeComponent()

    def InitializeComponent(self):
        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.SuspendLayout()
        #
        # button1
        #
        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
        #
        # listBox1
        #
        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
        #
        # textBox1
        #
        self._textBox1.Location = System.Drawing.Point(103, 15)
        self._textBox1.Name = "textBox1"
        self._textBox1.Size = System.Drawing.Size(139, 20)
        self._textBox1.TabIndex = 2
        #
        # label1
        #
        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:"
        #
        # label2
        #
        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"
        #
        # Form1
        #
        self.ClientSize = System.Drawing.Size(442, 447)
        self.Controls.Add(self._label2)
        self.Controls.Add(self._label1)
        self.Controls.Add(self._textBox1)
        self.Controls.Add(self._listBox1)
        self.Controls.Add(self._button1)
        self.Name = "Form1"
        self.Text = "Form1"
        self.ResumeLayout(False)
        self.PerformLayout()

    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
        os.chdir(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
            file_list.append(filename)
            self._listBox1.Items.Add(filename)
        #print(file_list)  # test
        pass

    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[0].ToString()


# final line added in Komodo IDE to make this run
Application.Run(Form1())

Run the code above in the Komodo IDE with this run line ...
C:/IronPython2.7/ipy.exe -u %F

Tcll 66 Posting Whiz in Training Featured Poster

whell then... +1

thanks for proving me wrong :)
I have a hunch Mono wasn't developed by MS, but I'll figure that out later. :P

still, I use PyOpenGL, so I stick with Python 2.7 :)
@anyone else: use whatever fits your project. ;)

panjiasmara 0 Newbie Poster

If you use express (free) version this will not give web template like django template.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

C# was Microsoft's answer to Java after Oracle gave them a hard time. It was designed by the same parson that did the original Turbo Pascal, Turbo C and Delphi.

My only problem with C# is the exessive verbosity, too much typing.

ddanbe 2,724 Professional Procrastinator Featured Poster

@ vegaseat: My only problem with C# is the exessive verbosity, too much typing.
I do it this way, because my quotes don't seem to work.
Why is too much typing such a problem?
If you write something like y = x; you probably have to add some comments to explain what x and y mean. If you have something like length = calculationResult; you don't have to add any comments.

Tcll 66 Posting Whiz in Training Featured Poster

Why is too much typing such a problem?

personally I feel it's better to use shorter var names and comment if needed.
it's not like it really matters... heh

referencing long var names is annoying and looks messy

the real question is: Why is commenting such a problem??

My only problem with C# is the exessive verbosity, too much typing.

I agree, the syntax is so messy it's outrageous (like Java)

BustACode 15 Light Poster

Looks great, but having followed Micro$oft since the late 80s, I quiver at any mention of them and anything good, or that I love, in the same sentence. And I do love Python.

I have seen M$ buy or get involved with technologies or products only to see those technologies or products wither and die as a result. They are the "Red Horse" of technology.

Best thing that ever happened to open-source, especially Linux, was that M$ tried to kill it, and not "help" or "cooperate" with it.

Also, relying on any product by Micro$oft means also suffering biennial user interface changes that will boggle the mind, as any Office user will attest to--Menu, "ribbon" or whatever 2013's is?

Then there is the "little" matter of their fun with grenades EULs.

I will eat green eggs, and ham. In the rain, or even on a train. I will not eat Micro$oft green eggs, and ham. Not in the rain, or even on a train.

Tcll 66 Posting Whiz in Training Featured Poster

they did try to kill python via the likes of IronPython which, for starters, is a nightmare to pick up.
and then the fact that most python extensions don't work with it...
(I took a shotgun to it when PyOpenGL wouldn't work with it)

what makes this good is that PythonTools wasn't developed by MS,
it was only developed for an MS product.

to add, I personally can't use anything above VS2010, so I'm not subjected to their garbage.
I refuse to subject myself to using an OS in which MS has full control over my stuff.
The latest Win I use is WinXP64 until MS pulls their S together.

BustACode commented: I didn't know that about IronPython. Typical for M$: "IronPython is an implementation of the Python programming language targeting the .NET Framework" +0
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.