Tuesday, October 28, 2014

Database from Ch 19 of Teach Yourself Python

Teach Yourself Python is a really good introduction to Python--my favorite out of the three introductory books I own. Chapter 19, on using databases, references a video game database. I couldn't find the database online, so below is the code I used to make it.

# -*- coding: utf-8 -*-
'''Code to construct database from Chapter 19 of 
Teach Yourself Python in 24 Hours by Katie Cunningham'''
import sqlite3

error = None
conn = sqlite3.connect('videoGames.db')
cursor = conn.cursor()
  
#create games table
sqlCreate = '''CREATE TABLE games 
               (title text, rating text, system text, year int)'''
try:
    cursor.execute(sqlCreate)
except sqlite3.OperationalError as e: 
    error = e

#add data, if database doesn't already exist
if not error:
    print "Successfully created database...populating table"
    gameDataAll=[('Tales of the Abyss', 'T', '3DS', 2011),
              ('Adventure Time', 'E10+', '3DS', 2012),
              ('Hollywood Crimes', 'T', '3DS', 2011),
              ('Forza Motorsport 4', 'E', '360', 2011),
              ('Sonic Generations', 'E', '360', 2011),
              ('Forza Horizon', 'T', '360', 2012),
              ('ZhuZhu Pets', 'E', 'Wii', 2012)];
              
    for gameData in gameDataAll:
        print gameData 
        sqlAdd = '''INSERT INTO games (title, rating, system, year)
                    VALUES (:title, :rating, :system, :year)'''
        cursor.execute(sqlAdd, {'title': gameData[0], 'rating': gameData[1],
                                'system': gameData[2], 'year':gameData[3]})   
    conn.commit()  #commit changes otherwise they will not be saved
else:
    print "Didn't create database because", error
    sqlShow = '''SELECT * FROM games'''
    selectResults = cursor.execute(sqlShow)
    allGames = selectResults.fetchall()
    print "\nThe games table contains the following rows:"
    for game in allGames:
        print game
          
#close shop
cursor.close()
conn.close()
Code highlighting done at highlight.me.

Saturday, September 20, 2014

Pyside or PyQt for beginners?

As I mentioned in the previous post, my hobby recently has been porting Summerfield's book from PyQt to PySide (the code is in the PySide Summer repository).

Now that I'm about halfway through done with the translation process, I have inexorably been pulled to favor PyQt over PySide, at least for beginners. This is mainly because it has a more active community working hard to maintain the code, and there is better overall documentation in PyQt than PySide.1
 
This recommendation isn't based on thinking PyQt is significantly better than PySide: they are roughly the same packages.2 That said, PyQt has a much more active user community, with some amazing developers, such as Phil Thompson, who quickly address bugs and other serious issues. PyQt has kept pace with Qt's version 5, while PySide is still tracking Qt 4. Nokia used to actively maintain PySide, but my understanding is they have dropped it, so there is now no longer a cadre of professionals working on active maintenance. There seem to be lots of bug reports piling up, for instance.

In my experience in the open-source world, when it comes to things like navigating install hell, finding out if something is a feature or a bug, or learning how to optimize code, community is invaluable. There is a large body of know-how that only emerges if a lot of people use something. For that reason alone, I recommend beginners use PyQt to cut their teeth.


Also, PyQt has much better documentation. I have found, countless times, for some reason PySide docs leave out crucial details about methods and classes that PyQt includes. Not sure why, but the automatic documentation generator is much better for PyQt (for one representative example, compare the online docs for QTextEdit.setAlignment method for the two frameworks).

There is another good reason: Summerfield's book is the best introductory book on Qt programming in Python, and it uses PyQt. It rescued me me from floundering as a Qt  cargo cult programmer, where I would just hunt (Google) and peck out something that sometimes worked. His book teaches the fundamentals of the framework from the ground up. Admittedly, the PySide Summer repository does take the sails out of this reason a little bit, as it should make it easier for beginners to work through his book with PySide. (Yes, this entire post is tinged with irony in a few ways).

The main exception to my argument is going to apply to a tiny fraction of beginners. Namely,  if you are working on a commercial product, and don't want to pay a licensing fee, then you should use PySide. The reason PySide exists in the first place is that PySide has a less restrictive license than PyQt. If you want to use PyQt for commercial software, you have to buy the commercial license from Riverbank Computing. This restriction does not hold for PySide.

Note many people start out with dollar signs in their eyes, but in practice if you are building a little application, and are truly a beginner, you could easily build in PyQt first while learning. If you want to commercialize the product you could easily port to PySide.

I should be clear: my argument isn't that PyQt is objectively better than PySide, but that because they are basically the same framework, for beginners I'd suggest going with the package with the most active community.

Notes
1 That is not to say the documentation is fantastic for PyQt. For someone neutral about C++ versus Python, I would recommend starting with Qt in C++. The documentation is incomparable, the number of books you can get, etc.. This post is focused on Python, as between Qt and PyQt, there is really no contest.

2 They are roughly, though not exactly, the same. The PySide binding is built using Shiboken while PyQt uses SIP. This can be a nontrivial difference, as SIP is more mature than Shiboken. Plus, PyQt is on version 5, as mentioned. The differences, as of Fall 2014, don't seem significant enough to be deciding factors. (Note added in early 2015: it is clear this will become a larger factor as time goes on. So far there is talk, but no palpable progress, in moving PySide to Qt 5).

Friday, September 12, 2014

From PyQt to PySide

My hobby the the last few weeks of the summer has been to port Mark Summerfield's book on PyQt to PySide (Qt is a GUI framework written in C++, and PySide/PyQt are Python bindings to this framework). (Note added: I have subsequently completed the project).

The work, so far, is up at Github in a repository called PySideSummer. Frankly, most of the work is in updating the code from 2008 (when Summerfield's book was written) to 2014. Even within PyQt, a lot has changed. We now have new-style signals-and-slots, lots of classes have been deprecated (e.g., QWorkspace), methods have become obsolete (e.g., QColor.light()), and there is a new API.

Now that I've been doing it a few weeks, I can translate between the two frameworks pretty quickly, but I am keeping my foot on the brakes. I'm taking my time because I want to actually understand what is going on in each chapter. I expect to do about a chapter a week until I'm done.

Next post: which is better: PyQt or PySide?

Sunday, July 13, 2014

Python IDEs: Pycharm versus Spyder

Note (added 9/29/2015) this post is a bit obsolete:  in Spyder, be sure to go to Preferences-Editor-Code Introspection/Analysis and turn on Automatic code completion.
----------------------
After just a day with Pycharm (and a few weeks with Spyder), it is clear that for PySide coding, Pycharm wins. However, for scientific computing, especially for those who prefer a quick-responding Matlab-like IDE, Spyder definitely deserves drive space.  

I've been using the Spyder IDE for a few months now. Strangely, while tab completion works in its Python shell, it is not always seamless in the editor window (as discussed at http://code.google.com/p/spyderlib/issues/detail?id=1254).

Note added: to minimize this issue, be sure to go to Preferences-Editor-Code Introspection/Analysis and turn on Automatic code completion. This has made PySide tab completion work in my editor, and now I am back to using Spyder for PySide coding, and this makes this post somewhat obsolete frankly!

I've never placed much stock in IDEs, but as I watched some excellent PySide tutorials (found at http://www.yasinuludag.com/blog/?p=98), it seemed Yasin Uludag was able to type PySide code at mach speeds partly because of the IDE he was using (and also partly because he is a badass PySide ninja). To see for myself, I installed the free version of Pycharm yesterday.

First good thing I noticed: no install hell. Installation was easy on Windows 7. It automatically saw my Anaconda distribution of Python, and automatically used iPython for command line work.

Upon firing it up, the first thing I noticed was that Pycharm was really slow to load, and also very sluggish in response to basic commands (even entering text or surfing the menu system). Thankfully, it grew more responsive over time (or perhaps my temporal expectations adapted to its intrinsic pace). Despite the slow start, after about five minutes of exploring (with the help of the Getting Started page), I started to appreciate the crazy horsepower under my fingertips.

I haven't really touched the surface of Pycharm. I still feel like a 16 year-old who just learned how to drive stick, and was given the keys to a Ferrari. A bit in over my head, but excited nonetheless. Pycharm seems seamlessly integrated with version control, unit testing frameworks, has all sorts of refactoring functionality built in, among other things I have not yet explored and have never used before. I won't go over all the details, as I am just starting to learn them myself, so if interested I'd ask Google.

Tuesday, July 08, 2014

PySide event handling: pos versus globalpos

I'm playing around with Qt in Python using PySide. It is one of the steepest learning curves I've ever been on. I figure I'll start dropping little examples here. The following is a really simple example to demonstrate the difference between the pos and globalPos of an event in a window. Fire up the program, click within the window, and then drag the window and click within it again. It will print out globalPos() and pos() of a mouse click in the command line, and should be fairly self-explanatory.
# -*- coding: utf-8 -*-  
''' 
Click to see coordinates to get a feel for pos versus globalPos of an event  
''' 
   
from PySide import QtGui, QtCore  
   
class MousePos(QtGui.QWidget):  
    def __init__(self):  
        QtGui.QWidget.__init__(self)  
        self.initUI()  
       
    def initUI(self):  
        self.setGeometry(50,50,300,250)  
        self.show()  
   
    def mousePressEvent(self,event):  
        if event.button() == QtCore.Qt.LeftButton:  
            msg="event.globalPos: <{0}, {1}>\n".format(event.globalPos().x(), event.globalPos().y())  
            msg2="event.pos(): <{0}, {1}>\n".format(event.pos().x(), event.pos().y())  
            print msg + "  " + msg2  
       
def main():  
    import sys  
    qtApp=QtGui.QApplication(sys.argv)  
    myMousePos=MousePos()  
    sys.exit(qtApp.exec_())  
   
if __name__=="__main__":  
    main()  
One of my goals is to see if this code formatting worked in blogger. I did it at codeformatter.blogspot.com but am looking for better ways to do it. I want examples to be simple: cut, paste, and it works in your interpreter. Python is all about using space for syntax, and I had to do too much futzing to get the syntax right.

Sunday, March 23, 2014

iPython: clear current line

When you have some junk on the command line, and want to clear it, many interpreters (e.g., Matlab) would use <ctrl>-c. For reasons I don't understand, in the iPython command line, <shift><esc> will clear it up (while <ctrl>-z will undo your most recent action). If you really wanna go crazy, <ctrl>-l clears the entire screen.

Saturday, February 15, 2014

Saving an entire project in Code::Blocks

You are working with projectx in Code::Blocks, and want a copy of  the entire project with all its files
(e.g., header files). You try to save your project by entering File-->Save Project As, but it only saves a single cbp file. What do you do? You could copy over all the files individually, but that would be very time consuming for complex projects.

A more efficient method exists, but is not obvious from the Code::Blocks menu system. It involves two easy steps: 
1. Save template of projectx 
With projectx open, click File-->Save Project as Template and enter whatever name you want for this template. 
2. Open a new project from that template 
Click File-->New-->From Template, then pick the name you entered In Step 1. After clicking Go the program will request a folder to place the project. When it asks if you want to change the project name, you should do so unless you want it to have the exact same name as the template from Step 1. 

That's it. Those steps should give you an exact duplicate (potentially with a different name) of projectx.