1,105,534 Community Members

Review of Python Tools for Visual Studio

Manufacturer:
Microsoft
Product Website:
URL Screenshot of http://pytoo….codeplex.com
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:
9/10
Member Avatar
(jeffcogswell)
Reputation Points: 175 [?]
Q&As Helped to Solve: 5 [?]
Skill Endorsements: 10 [?]
 
1
 

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: DebuggerRunning1.png


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: inspect.png


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: watch.png


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: locals.png


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:

intellisense.png


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: intellisense2.png


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: intellisense3.png

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): intellisense4.png

Finally, I wanted to test one more thing with Intellisense, and it failed. See if you can see the problem here: intellisense5.png


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:

rename2.png


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 .

Attachments DebuggerRunning1.png 71.46KB inspect.png 5.59KB watch.png 13.34KB locals.png 19.1KB intellisense.png 8.54KB intellisense2.png 10.52KB intellisense3.png 12.34KB intellisense4.png 10.17KB intellisense5.png 13.58KB rename2.png 23.43KB
Member Avatar
Dan08
Junior Poster
138 posts since Jul 2009
Reputation Points: 8 [?]
Q&As Helped to Solve: 9 [?]
Skill Endorsements: 0 [?]
 
0
 

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

Member Avatar
Tcll
Posting Pro in Training
443 posts since Jan 2010
Reputation Points: -4 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

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.

Member Avatar
vegaseat
DaniWeb's Hypocrite
6,984 posts since Oct 2004
Reputation Points: 1,544 [?]
Q&As Helped to Solve: 1,872 [?]
Skill Endorsements: 67 [?]
Moderator
 
0
 

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.

Member Avatar
Tcll
Posting Pro in Training
443 posts since Jan 2010
Reputation Points: -4 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

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.

Member Avatar
vegaseat
DaniWeb's Hypocrite
6,984 posts since Oct 2004
Reputation Points: 1,544 [?]
Q&As Helped to Solve: 1,872 [?]
Skill Endorsements: 67 [?]
Moderator
 
0
 

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

Member Avatar
Tcll
Posting Pro in Training
443 posts since Jan 2010
Reputation Points: -4 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

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

Member Avatar
vegaseat
DaniWeb's Hypocrite
6,984 posts since Oct 2004
Reputation Points: 1,544 [?]
Q&As Helped to Solve: 1,872 [?]
Skill Endorsements: 67 [?]
Moderator
 
0
 

There is a NET version for Linux called Mono.

Member Avatar
vegaseat
DaniWeb's Hypocrite
6,984 posts since Oct 2004
Reputation Points: 1,544 [?]
Q&As Helped to Solve: 1,872 [?]
Skill Endorsements: 67 [?]
Moderator
 
0
 

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

Member Avatar
Tcll
Posting Pro in Training
443 posts since Jan 2010
Reputation Points: -4 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

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. ;)

You
Post:
Start New Discussion
View similar articles that have also been tagged: