Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Tuesday, July 2, 2013

QPlainTextEdit with setMaximumBlockCount performance regression

Recently while working with ipython qtconsole, i realized that it is easy to freeze the qtconsole or any app embedding the it by simply doing a "for i in xrange(10000000):print i" loop, then all arguments about separate kernel process safety etc. are voided. Since this is not something i liked, i set about to fix it in true nature of open-source development (scratching my own back). In this post i'll describe some Qt issues, benchmarks and the approaches i took and how you too can deal with similar problem of overwhelming text input to your text buffer.
Note: The ipython pull request https://github.com/ipython/ipython/pull/3409 is part of this experiment.

The Problem:

The qtconsole widget is a QPlainTextEdit, with the maximumBlockCount set to 500 by default, which is a very small buffer size by any standard. However, despite this, in case too much text is written to the QPlainTextEdit, it takes too much time drawing the text and the application appears to be frozen This is because the Qt event loop is blocked by too much time consumed by drawing the QPlainTextEdit and incessant stream of new text to draw at a faster rate than QPlainTextEdit can render.

The Solution Approaches:

My first though at the problem was to use a timer to throttle the stream rendering rate, and append text to the area only every 100ms. That wouldn't cause any perceptible usability loss, but make the program more responsive. Also, another essential idea was to only send the maximumBlockCount number of lines of text ot the QPlainTextEdit. It seems that QPlainTextEdit is very bad at render performance if text is clipped by limiting maximumBlockCount, contrary to its single major use as a way to improve performance and memory usage.

An initial look into the ipython code made it clear that the test code was giving about 8000 lines per stream receive, which i was glad to clip to maximumBlockCount and coalesce multiple text streams into a single appendPlainText call every 100 ms. The qtconsole seemed very responsive, terminating the test print loop without any perceptible delay. All was well, i could go to sleep peacefully now, except for a small glitch which i realized soon enough. Due to a bug, my timer loop wasn't really doing anything. Every stream from ipython kernel was being written to the widget. How then was the widget so responsive, an attentive reader might ask. This post attempts to provide an answer to that very question.

The following are plots of time taken to append plain text to QPlainTextEdit using the code linked here. The x axis is the number of lines appended per call and the different lines are for different maximumBlockCount of the QPlainTextEdit
Appending to an already full buffer
 Clearing and then appending text
 Appending text to empty widget

In all the above cases, the final result is same because the number of lines appended is equal to maximumBlockCount so that all previous content is gone.
As you can see yourself, simply appending text to a full buffer is *very* expensive, so much so that it is almost an order of magnitude larger than clearing the text and then appending for ipython's default case of maxumumBlockCount = 500. All appends are fast until any line overflows the maximumBockCount, when onwards it becomes very expensive to append any more content. I intend to modify the ipython pull request in view of this seemingly bizzare result and attempt to improve the performance further. Hopefully, this would obliterate the need to have a timer based stream output loop and the related complexity. Ideally, someone should fix this right at Qt level, but i do not yet feel confident to do it. Until that happens, this simple workaround should be good enough.


PS: Comments, feedback and further insights welcome

Thursday, November 11, 2010

python editors in python: spyder and iep

This post is gonna be about python editors (IDEs if you may call, not but quite so)

If you are looking for IDEs, check out pydev and SPE, these are some of the best ones out there with integrated debugging features. There's also a wing editor which many people say is quite good, but i've never used it

Here i'm gonna list opinions about IEP and Spyder. I'm really interested in both of them and run their repository version.
My main issue is i want a good editor for cython, for which i am willing to get my hands dirty (a bit) and add some features myself (see http://powerpan.blogspot.com/2010/10/cython-functions-coverage-revsited.html), so if any of you can help me or have an opinion please do so.

Common features:
Both are python editors written in python (pyqt)
Both provide code completion support and outline
Both have integrated python shells

Differences:
Pros:

Spyder seems a bit more mature project
Spyder has ipython shell which is more useful than a python shell
IEP has outline support for cython

Cons:
Spyder seems to excessively misuse screen real estate - see this issue (editor areas are quite small)
IEP lacks some features such as tree file browser, shell variables, variable occurances marker, pylint support annotation
IEP is officially only for Python3, though you can surely work with python2 files (Also check http://code.google.com/r/pankaj86-iep-python2/source/browse if you really want to run it in python2 only)

Features both lack:
Graphical Debugger: get the code from pydev/winpdb to provide a graphical debugger
Cython support: I could certainly do well with more cython support. Outlining (iep does that), completion support in cython and goto definition (including into cython file from a python file)
Profiling support: Simply run profiling and put the result data into a table (spreadsheet widget)
Documentation: More documentation is needed for both the projects, especially developer documentation to implement new interesting plugins, such as profiling, debugging etc
Also it'd be cool if tooltips could be added to the editor to show documentation and other information on hovering on words in the editor, as in pydev

Few ideas:
Merge features from IEP to Spyder and vice versa. Add new features to both. Having two different projects is good in a way as it keep diversity and help in bringing new ideas. However that shouldn't mean they are independent without any co-operation. Both should surely work together to bring new features.

NOTE: The content may get outdated as you are reading it

Saturday, October 30, 2010

cython functions coverage revsited

A few days back i showed how to get coverage of cython functions using Ned Batchelder's coverage.py
In that post i had posted a patch to coveragepy to enable cython function coverage.

However i realize that many of my friends have never applied a patch before, dont have admin rights on few machines few other problems which may hinder their using this new feature, so here's a good new for you.

I've rewritten the patch into a single file pyx_coverage.py . You can directly use this file instead of 'coverage' command to get cython function coverage, no need to patch anything. You still need to have Ned's coveragepy installed though.

All commands/options/configuration files for coveragepy are applicable here too.

To find coverage of cython files (pyx extension) you need to do following:
1. compile cython code to 'c' with directive profile=True
2. keep source pyx files in same locations as the compiled .so files
    i.e. use 'python setup.py build_ext --inplace' or 'python setup.py develop'
3. run coverage (this file) with the option timid enabled (can also set in in .coveragerc)
    i.e. 'python pyx_coverage.py run --timid my_module.py'

You can use nose test collector as follows:
$ python pyx_coverage.py run /path/to/nosetests /path/to/source

replacing the /paths as appropriate

Download the file from here: https://sites.google.com/site/pankaj86/files/pyx_coverage.py

Reader's Bonus: If you can help me write a python c extension for this treat assured.
Hint: See Ned's coverage.tracer python c extension.

Saturday, May 29, 2010

numpy array performance / divide and conquer considered harmful

This is again a post about python code speed, the data and inference are more than a few months old but still valid.
Here's a spreadsheet showing speed of array math operations (+, -, *, /) between numpy arrays and python lists.
Check this spreadsheet to see the timings of various operations
https://spreadsheets.google.com/ccc?key=0AomYDYyBBNkkdHAtMkdHMF9TZ29lMmZQV3UwYkxWNFE&hl=en

The operations I considered for comparison were:

  • x+0.1
  • x-0.1
  • x*0.1
  • x/0.1
  • x*(1/0.1)
  • x+y
  • x-y
  • x*y
  • x/y
  • [p+yp[j] for j,p in enumerate(xp)]
  • [xp[j]+yp[j] for j in xrange(i)]
where x and y are numpy arrays, xp and yp are python lists, all of size N which is varied for the comparison.
The raw timings data is available here:
    https://spreadsheets.google.com/pub?key=0AomYDYyBBNkkdHAtMkdHMF9TZ29lMmZQV3UwYkxWNFE&hl=en&output=html

    See the timings plot yourself
    Conclusion:
    • Use numpy arrays for size > 10
    • Avoid division as much as you can to improve the speed of your numerical codes
    • Instead of x/0.1 do x*(1/0.1) . This itself causes large speedup as N is increased.
    • x/0.1 and x/y take almost the same time
    • +, -, * take almost same time, / takes much more time, and its expense increases as N is increased.
    • Once again, do not divide.
    • The same thing is valid in cython code also. Avoid division even in cython code, and even if you are using double instead of numpy arrays (buffer). Rewrite expressions to minimize the usage of division operator.

    Wednesday, May 26, 2010

    cython timings test

    The TASK : To optimize cython functions

    Detailed: functions which depend on a once initialized attribute value

    This often comes handy in many cases, for example to write a Laplacian function of a scalar field in spherical/axisymmetric coordinate system, you would need three independent cases for 1,2,3 dimensions for performance purposes and if u do not write all functions as general 3D functions.


    The test CODE : test_kernel.pyx


    cdef class Kernel:
        cdef int dim
        cdef double (*func)(Kernel,double)
        def __init__(self, dim=1):
            self.dim = dim
            if dim == 1:
                self.func = self.func1
            elif dim == 2:
                self.func = self.func2
      
        cdef double func1(self, double x):
            return 1+x
      
        cdef double func2(self, double x):
            return 2+x
      
        cdef double c_func(self, double x):
            '''this is only to make function signature compatible with func1 and func2'''
            return self.func(self, x)
      
        def p_func(self, double x):
            return self.func(self, x)
      
        cpdef double py_func(self, double x):
            return self.func(self, x)
      
        cpdef double py_c_func(self, double x):
            return self.c_func(x)
      
        def py_func1(self, x):
            return self.func1(x)
      
        def py_func2(self, x):
            return self.func2(x)
      
        cdef double func_common(self, double x):
            cdef int dim = self.dim
            if dim == 1:
                return 10+x
            elif dim == 2:
                return 20+x
      
        def py_func_c_common(self, x):
            return self.func_common(x)
      
        cpdef double py_func_common(self, double x):
            cdef int dim = self.dim
            if dim == 1:
                return 10+x
            elif dim == 2:
                return 20+x

    Compilation command:
        cython -a test_kernel.pyx;
        gcc <optimization-flag> -shared -fPIC test_kernel.c -lpython2.6 -I /usr/include/python2.6/ -o test_kernel.so
    where optimization flag is either empty or "-O2" or "-O3"

    Cython optimization
    Tip 1:
    Type (cdef) as many variables as you can. You also need to type the locals in each function. Try to try to use C data types wherever possible.
    Tip 2:
    use:
        cython -a file.pyx
    command to generate a html file which shows lines which cause expensive python functions to be called. Clicking on a line shows the corresponding C code generated, highlighting expensive calls in shades of red. Try to eliminate as many such calls as you can.

    The TEST :

    time_kernel.py

    import timeit

    def time(s):
        '''returns time in microseconds'''
        t = 1e6*timeit.timeit(s,'import test_kernel;k1=test_kernel.Kernel(1);k2=test_kernel.Kernel(2);',number=1000000)/1000000.
        print s, t
        return t

    time('k1.p_func(0)')
    time('k1.py_func(0)')
    time('k1.py_func1(0)')
    time('k1.py_c_func(0)')
    time('k1.py_func_c_common(0)')
    time('k1.py_func_common(0)')

    time('k2.p_func(0)')
    time('k2.py_func(0)')
    time('k2.py_func2(0)')
    time('k2.py_c_func(0)')
    time('k2.py_func_c_common(0)')
    time('k2.py_func_common(0)')

    Timings :



    functiontime (μs)(ns)

    Optimization flag ->None-O2-O3sum(k1+k2)/2penalty
    1k1.p_func(0)0.201780.183210.180350.188450.193680.0000
    2k1.py_func(0)0.232240.185990.183930.200720.195411.7345
    3k1.py_func1(0)0.214770.189910.192520.199070.198024.3456
    4k1.py_c_func(0)0.233950.191960.192430.206110.197613.9311
    5k1.py_func_c_common(0)0.195660.184580.190620.190290.197673.9960
    6k1.py_func_common(0)0.219810.187070.189840.198910.195101.4237
    7k2.p_func(0)0.204480.183880.181940.19010

    8k2.py_func(0)0.217980.188590.184370.19698

    9k2.py_func2(0)0.204130.181240.181940.18910

    10k2.py_c_func(0)0.231140.191660.192380.20506

    11k2.py_func_c_common(0)0.198600.187830.187450.19129

    12k2.py_func_common(0)0.216090.187470.186400.19666


    Average0.215600.186810.187030.19648


    Result :

    The best is to write separate C function and a python accessor function.

    task
    functionpenalty cost (ns)
    C function + python accessor : base casep_func
    cpdef instead of defpy_func1.7345
    calling a cdef class method instead of a function pointer attributepy_func1,py_func24.3456
    one extra c function callpy_c_func3.9311
    (def + cdef) instead of (cpdef)py_func_c_common-py_func_common2.5723
    One C comparison vs one C function callpy_func_common1.4237

    Conclusion :

    As can be clearly seen that the results are clearly inconclusive :)
    This was a small test carried on my laptop with no controlled environment. Also thought the results seemed close to repeatable, nevertheless many trials should be conduction and each value should have a standard deviation also to check the repeatability. However one clear conclusion is do not forget to add optimization flags. Setuptools already does that for you.
    Also using a function pointer is not so bad after all. It would become more advantageous in case of more number of comparisons.
    Cython provides great speedups (who didn't know that :) ). The pure python version of py_func_common took 0.408μs for dim=1 and 0.518μs for dim=2
    These results are purely from python point of view. The effect of cdef/cpdef should also be considered in c/cython code which calls these functions.

    CAVEAT:

    I am no optimization expert. I have done this out of out of sheer boredom :)
    If anyone wants to verify, you are welcome
    Any information content is purely coincindental

    Tuesday, April 27, 2010

    Tracing python programs

    Coming with the easier python debugging enabled by the new gdb with python hooks is another awesome python feature coming in the new Fedora "Goddard" 13 release. That is tracing of python processes and their function calls. This feature is developed on top of systemtap, the linux analogue of Sun's awesome Dtrace system tracer.
    So what does it mean? For the uninitiated, it implements hooks (tracepoints) in the python main shared libraries (libpython.so and libpython3.so) so that systemtap can trace whenever a python function is entered/exited in any python process on the system. This means you can anytime check a python process to see which functions are being called and how many times etc. This has really cool uses. More information about this feature is available at https://fedoraproject.org/wiki/Features/SystemtapStaticProbes#Python_2

    Just to illustrate the use try the following examples (from the above link)
    First install python-debuginfo. Now add yourself to stapdev and stapusr groups or run the following command as root:
        $ stap /usr/share/doc/python3-libs-3.1.2/pyfuntop.stp
    This will display a top like output on the terminal showing the python functions which are called by all running processes and the number of times its being called. Its fun to watch, just run a python program and check all the functions being called :)
    Here's a sample output from my laptop

    PID                                                                         FILENAME   LINE                       FUNCTION  CALLS
     15479                                 /usr/lib/python2.6/site-packages/yum/packages.py    261                         verCMP  15768
     15479                                 /usr/lib/python2.6/site-packages/yum/packages.py    270                        __cmp__  15767
     15479                             /usr/lib/python2.6/site-packages/rpmUtils/updates.py    129                   returnNewest   9045
     15479                           /usr/lib/python2.6/site-packages/rpmUtils/miscutils.py     36                     compareEVR   1191
     15479                                 /usr/lib/python2.6/site-packages/yum/packages.py     48                   comparePoEVR    578
     15479                                 /usr/lib/python2.6/site-packages/yum/packages.py    296                          verEQ    556
     15479                                 /usr/lib/python2.6/site-packages/yum/packages.py     55                 comparePoEVREQ    556
     15479                                 /usr/lib/python2.6/site-packages/yum/__init__.py    778                             2
     15479                                 /usr/lib/python2.6/site-packages/yum/__init__.py    206                     _getConfig      2
     15479                                   /usr/lib/python2.6/site-packages/yum/config.py     69                        __get__      2
     15479                                         /usr/lib64/python2.6/logging/__init__.py   1026                          debug      1
     15479                                         /usr/lib64/python2.6/logging/__init__.py   1236                   isEnabledFor      1
     15479                                         /usr/lib64/python2.6/logging/__init__.py   1222              getEffectiveLevel      1
     15479                             /usr/lib/python2.6/site-packages/rpmUtils/updates.py    272                      doUpdates      1
    
    This shows the functions called during a 1 second interval (the script updates the display every second) by checking of available updates by packagekit.
    Another system script displays the python function call hierarchy of any program you run. Try this by running
        $ stap -v /usr/share/doc/python-libs-2.6.4/systemtap-example.stp -c python
    Now you will get a python terminal after a long hierarchy of function calls. Here you can see all python functions called for each line you enter on the python terminal. Its not as much fun, but useful if you want to check where all those extra unneeded function calls are being made.
    Read a short writeup from the developer of these features at http://fedoraproject.org/wiki/Python_in_Fedora_13 and also check http://press.redhat.com/2010/04/27/fedora-13-spotlight-feature-exploring-new-frontiers-of-python-development/

    Friday, April 23, 2010

    Easier cython/python/c debugging with new GDB

    We all know how debugging is an dreaded integral part of every programmer's work. It can also be fun sometimes depending on the time to deadline, complexity of the bug and time already spent.
    So if anyone is still left who does assignments or other programs without debugging (using print statements etc) then please consider learning it. Else you are simply increasing your work and frustration.
    For debugging in any programming language my advise would be to use the eclipse debugger gui which provides all the standard features present in any debugger and integration with java, c/c++, python and a host of other languages.

    This post was not about plain debugging. Its about the new features in GDB 7 (the GNU debugger) which enables writing pretty printers in python. More information can be had from the net. However it means a much easier debugging experience with cython. The good folks at Fedora have written some cool scripts to integration python scripting capability of gdb to enable easier cython debugging.
    Check out the awesomeness at https://fedoraproject.org/wiki/Features/EasierPythonDebugging
    In short now you can do the following easily with the new gdb

    • automatically display python frame information in PyEval_EvalFrameEx in gdb backtraces, including in ABRT:
      • python source file, line number, and function names
      • values of locals, if available
    • name of function for wrapped C functions
     This gonna make my life easier, especially since my DD project is in cyton/python.

    Also not to forget the uber cool features it could enable not only for python developers but for all. As an example check out the blog at http://labs.trolltech.com/blogs/2010/04/22/peek-and-poke-vol-3/

    Saturday, October 3, 2009

    thermal handler : protect your computer from overheat

    So recently i started encoding some of the videos i had from dvds into compressed formats as the dvds are getting scratched and damaged. So i used the avidemux program for it. However my laptop gets overheated a lot during high cpu usage.
    Other problems with overheating came when i had to run my dsmc and other assignments. Since they run for a looong time, my laptop overheats and i used to keep it hanging on its side during overnight runs. To my horror once when i compiled openfoam on my laptop overnight, i saw it shutdown in the morning with a failed compile and overheat. So here's my solution for all those who suffer from the problem of overheating computers (for linux users only).
    Checkout the all new "thermal handler" from yours truly. The solution for all your computer overheat problems due to high cpu usage.
    What it does:
    Checks the temperature periodically and pauses processes using high cpu when a certain temperature is reached (default 90) and resumes them when the temperature falls below a certain value (default 65). None of your data crashes. The programs resume from the same state they were paused. No data loss. (Note that root processes cant be paused by the user)
    What you need to do:
    just run from a shell:

    $ python thermal_handler.py [temp_lo [, temp_hi]]

    Here's thermal handler at work:



    Download it from here : http://home.iitb.ac.in/%7Epankajp/web/downloads/thermal_handler.py

    EDIT: Thanks to Prashant Agrawal for reporting that the initial version didn't work on AMD cpus and helping me to test. I've updated the file to work on AMD cpus now. check it out

    Friday, October 2, 2009

    animate2

    Now i present before you the much improved animate2.
    Here are the major changes

    • Plot saving is fixed when multiple subplots are present
    • animate() is retained for compatibility, new users are expected to use animate2() with changed api for the function
    • Much more customizability
    • Plot frame traits (properties) can now be specified. Ex: plot title, axes labels, ticks, colors etc using extended traits notation to set the plot object properties
    • Each plot (line) can be customized. Plots can now be of various types such as scatted, line etc. Their properties can also be set such colors, thickness, style (dot-dash etc). Plots can also be labelled to add legends to the plot
    • Read the docstrings and the examples in __main__. They explain a lot of common uses.
    So what are you waiting for. Try the latest animate2. Dont forget to check out the demo sample usage in the '__main__' section of the file
    Check out the video below



    Video with subtitles explaining the video is available here:
    http://home.iitb.ac.in/%7Epankajp/web/downloads/animate2.mkv


    Requirements:
    To run this you will need the Enthought tool suite ETS (only traits with wx backend and chaco are required)
    Hope this is useful for someone.
    You can get the code animate.py from here that is:
    http://home.iitb.ac.in/%7Epankajp/web/downloads/animate.py

    Wednesday, September 23, 2009

    Animate simulations in python

    I've recently written a nice short code in python to animate the results (plots) of a simulation using chaco (part of Enthought ETS)
    It is not actually very difficult, but i've just made up this one for myself, and it also has some cool features, so i thought i'd share it with others may as well benefit from it.

    • This if useful for you if you ever do coding in python and need to plot somethings which may change with time. Example lets say you are plotting the evolution of temperature over a rod with time or solving a 1D Euler equation (say shock tube problem)
    • This code provides a simple function to do it easily.
    • You can play-pause the code (simulation) at any time.
    • You can zoom-pan theplot
    • You can plot multiple subplots in a single window (Example the velocity, density and pressure in a shock tube problem)
    • You can edit axis labels, font, grids using gui
    • You can save the plots
    Usage:
    This is the only function defined in the file  you need to know:
    def animate(func, delay=0.1, total_time=0.0, time_factor=1.0, size=(800, 600), title='Plot'):
        '''function to animate the values returned by a function
       
        func : function which returns a tuple of x,y values to animate on each call
            x is shape (N,), y is shape (N,) or (p,N), N is number of points, p is number of plots (properties)
        delay is the time interval in which to call the func after the previous func has returned(seconds)
        total_time is the time at which to stop the animation
                animation will stop when total_time > self.time / time_factor
                total_time <= 0 will continue indefinitely
        time_factor is the time to display as title (displayed_time=time/time_factor)
        In the plot window:
            pressing 'p' key will toggle animation play-pause
            pressing Ctrl-S will open a dialog to save a rendering of the plot
            pressing 'ESC' will reset the zoom level of the plot
            double clicking on some parts of the plot allows you to edit them in a gui,
                (axis titles, grids, ticks etc)
            if the window becomes unresponsive, pause the animation for a while
        '''


    The docstring explains most of the things you need to know.
    Here's how you could use it:
    First we see how to animate a single plot (A moving sine wave in this case)
    from animate import animate
    from numpy import linspace, sin
    x = linspace(-10, 10, 101)
    i = 0.0
    def get_data():
        global i
        i += 0.1
        return x + i, sin(x + i)
    animate(func=get_data)

    The above code snippet will generate a nice moving animation window. Here's a plot from the same


    Plotting multiple values is just as simple. You only need to pass on a tuple of the y values:
    from animate import animate
    from numpy import linspace, sin, cos
    x = linspace(-10, 10, 101)
    i = 0.0
    def get_data2():
        global i

        i += 0.1
        return x + i, (1 / (1 + x ** 2), sin(x + i), cos(x + i), sin(x + i), cos(x + i),)

    animate(func=get_data2)
    Here's a plot from the above snippet:

    As you can see i have tried to make it as easy as possible without losing out on functionality.

    Requirements:
    To run this you will need the Enthought tool suite ETS (only traits with wx backend and chaco are required)
    Hope this is useful for someone.
    You can get the code animate.py from here that is:
    http://home.iitb.ac.in/%7Epankajp/web/downloads/animate.py

    Saturday, August 22, 2009

    eclipse+ for python (pydev)

    This semester i have taken a course in particle methods for fluid flow, whose instructor is a big fan of python, and has written large applications in python. So most of my classmates have indeed chosen to use python for the assignments. As they mostly use MS Windows, it is easier to install some python bundle such as EPD or python(x,y). I'd like to recommend python(x,y) for windows users. Though i myself don't use windows (i use Fedora 11 x64 fyi), i did try python(x,y) at my home this summer. (I know epd since much before that). The only reason for this is that python(x,y) includes eclipse with pydev, and it make much more sense to use an ide in the learning phase than using the silly notepad on windows (or any other advanced notepad). For those who are beginning afresh, here are a few clues why you should use an ide.

    • Code formatting is easily performed in pydev. Try commenting out a 20 line function your editor. (pydev hint: source->comment menu)
    • Syntax checking: You don't need to run you module to find out that you missed a semicolon after an if statement, the annotations in the editor will help you. Many more annotations to guide you to catch errors.
    • Code completion: Do you remember if the function inverse tan (arc tan) in math is called arctan or atan? (pydev hint: try math. and check if its arctan or atan)
      Do you remember the arguments of the asarray function of numpy or whether it makes a copy of the array? (pydev hint: check the documentation by hovering the mouse on the function)
    • Refactoring: Though pydev does not have the awsome refactoring capabilities of the statically typed languages (its difficult in python) it can still rename attributes and methods across modules with sufficient accuracy.
    • Templates: Do you find yourself bored typing the bolierplate code for classes or unittests or new modules? The templates are you friends. Example the new pydev module dialog box will help you easily create boilerplate code for classes and unittests. Typing 'main' in the editor will complete it to "if __name__ == '__main__':" block
    • Debugger: This cannot be emphasised enough. If you are not using a debugger, you have not been coding enough. It simplifies the task of locating the errors in a program. You can pause, continue, step through the code and check the values of any variable defined in the program. You can create conditional breakpoints and watch arbitrary expressions. Hovering over any attribute displays its value, selecting an expression displays its values. You can also switch to any frame. The debugger is probably the biggest benefit of using an ide like pydev.
    Ok so all this was just to make programming beginners have a look at pydev ide. If you find anything unclear or want a short guide to do something please leave your comments and i'll try to help if possible.
    In future i'd like to post a short note on beginners use of pydev and the common tasks you need to know. Tell me if you'd like to have it soon rather than later