MySQL for Python

Author: Albert Lukaszewski
Publisher: Packt

MySQL for Python is a good book for any beginning to intermediate Python programmers who want or need to get their minds and hands on a crash course in SQL programming and MySQL administration.

I base the opinion above on the fact that I am someone who is comfortable with Python, but does not code in it often during my job. I am also someone who can work his way around a MySQL database without having to research every SQL command; my knowledge of Python and MySQL is functional, but not expert.

The book’s format is one that I would think someone who didn't know what they were doing with MySQL would find helpful. Each chapter is dedicated to performing a certain set of MySQL tasks; for example Chapter 7 is titled “Creating and Dropping” (as in tables). The chapter opens with a quick discussion about what information the chapter is supposed to convey. Then it moves on to which commands one will use in MySQL to perform the desired tasks. After these commands are discussed, the book then goes into how to perform the same commands in Python. Each chapter ends with a project that is supposed to challenge the reader to create something that exemplifies the chapter's topic.

One area where I find the book lacking is that there is no mention of Python3 or the changes that one's code would require to make it compatible with Python3 vs Python. For example, there are a couple of code examples in the book that heavily rely on the function xrange(). Not that xrange() is bad function to use, but that particular function doesn’t exist in Python 3. I could theorize that maybe the author didn’t want to complicate the idea of using Python as a tool to learning SQL, but it does limit the amount of time that the content stays relevant.

A part of the book that I did find quite good was the quick and easily understandable explanation of the various join functions in Chapter 13. Although the descriptions were a little short, the brevity was acceptable because of the included Venn diagrams to help illustrate the how the joins worked logically. This was a great touch for helping someone learn these concepts; it was also the first time I’ve seen Venn diagrams used to teach someone about joins.

I recognize I might have been overly harsh on this book review, but that doesn’t mean I wouldn’t recommend it for the right person. I feel the right person for this is someone who is already comfortable with Python and wants to expand their knowledge to include the basics of MySQL administration and SQL programming.

Project Euler: Problem 9

Happy New Year Ladies(?) and Geeks

Trying to get the year off to a good start, I'm posting up my solution for the ninth Project Euler problem. I'm not going to spend a lot of time talking about it, because the solution is a pretty easy one. Here is the code in Python:

  1. #!/usr/bin/python3
  2. """
  3. python solution for project euler problem #9.
  4. """
  5.  
  6. print( [a*b*(1000 - b -a) for a in range(1,500+1) for b in range(1,500+1) \
  7. if a * a + b * b == ((1000 -b -a) * (1000 - b - a))][0])

And here is the code in Haskell:

  1. module Main where
  2.  
  3. main :: IO()
  4. main = print . head $ [a*b*(1000-b-a) | a <- [1..500] , b <- [1..500], a ^ 2 + b ^ 2 == (1000 - b - a) ^ 2]

See, it really is that simple. There really isn't anything interesting between to the solutions, but I would like to make a quick note on the luxury of being able to use “head” in Haskell to simplify the whole process. In the Python solution, the answer is generated twice, that's just the nature of the algorithm, and to just get one number, I just ask for the first item in the list. Thanks to Haskell's lazy evaluation, I only have to calculate the answer once, and I think this may be reflected in the run times.

So now the part that I know everyone loves to read the most, Times:

python-2.6.6 : .165s
python-3.1.2 : .110s
haskell(runghc) : 1.921s
haskell(compiled) : .086s

Inspiration

First off, let me apologize for not writing in a long time, I haven’t forgotten about my blogging duties. Life has just forced a slight change of course for me a couple of months ago. Although I am still learning and growing, what I have been learning has been of a more personal nature. And since this blog is a tech blog I really don’t feel completely comfortable putting my personal developments right next to my technical ones, but I’m gonna take a break from my comfort zone to talk a little bit about something not so technical anyway.

Inspiration isn’t really a technical topic, but no less important when it comes to doing technical things. We in the technical field are quite lucky, we (generally) learn about our love for all things binary at a younger age, and pick our careers based on this love. But as the cliche goes, “Familiarity breeds contempt.”, one day we wake up dreading the idea of going to work, hating our job, and are (probably) none to happy about life either. The activity that we use to spend hours of our off work time doing, because we loved doing it, now begins to feel more like an obligation or a chore. People call this burnout, and the usual solution is to take a vacation. For most cases of burnout that works, but what about the cases where a vacation doesn’t get you out of that funk? That is when you need a moment of inspiration to allow you to rediscover why you picked your computer career in the first place.

Although this hasn’t happened to me in my career (yet), this did happen to me concerning this blog. The changes in my life that I eluded to earlier have had a direct effect on my writing, both extra curricular programming and blog writing, which I enjoy. I needed a moment of inspiration to help me break through my writer’s block and get back to coding and posting. That moment came to me a little while ago when I got an email form a reader named Dylan who wrote,
"I'm a kid that's trying to learn coding. I have started down my path of Python. I found your site because I have been using Python to solve the problems. Your code is really good and has helped me out a lot. So I thought I would give you a shout out and a thanks.

Sincerely, Dylan"

This simple little email has given me the inspiration I needed to remind myself of why I started blogging in the first place. For me it’s about sharing with others the things I learned. So that hopefully someone else out there will benefit from my time spent figuring something out.

So long story short, when you get to do what you love for a living or a lot in general, sometimes you forget that you loved it. That is when you need a shot of inspiration to remind you why you why you loved something in the first place and I hope you get it when you need it.

Since this is the holiday season, I doubt I’ll post again this year. So I wish you all the happiest of holidays, whatever you celebrate, and a better year for you next year.

Tame the Snake to Sit on the Couch

A while ago I came across an aritcle that talked about using python with couchdb. Since I'm interested in learning about the whole NoSQL movement and am trying to understand where this new style of database server fits in the schema (sorry, I couldn't resist) of things I decided to spend a little time getting to know CouchDB better.

The system that I build this script on, tested with, and designed for is Ubuntu (I'm running 10.10 if anyone cares to know). Although I installed CouchDB through apt-get, I decided to get couchdb-python through easy-install. I did this because the website documentation for couchdb-python is written for the most recent version, and the apt-get version is a little out of date.

So after you've installed Couchdb and couchdb-python you can now run the script below:

  1. #!/usr/bin/python
  2. '''
  3. Simple script to start playing with the couchdb python package.
  4. '''
  5.  
  6. import os
  7. import subprocess
  8. import re
  9. import sys
  10. import couchdb
  11. from couchdb.mapping import TextField, ListField, DictField
  12.  
  13. class System(couchdb.Document):
  14. _id = TextField()
  15. _rev= TextField()
  16. uname = ListField(TextField())
  17. packages = DictField()
  18.  
  19. def get_packages():
  20. '''
  21. gather all of the packages on the system, and return a dictionary with
  22. the package name as the key, and the version as the value.
  23. '''
  24. process = subprocess.Popen("dpkg-query -W -f='${Package} ${Version}\n'", stdout=subprocess.PIPE, shell=True)
  25. (proc, error) = process.communicate()
  26. sys.stdout.flush()
  27.  
  28. if error:
  29. print(error)
  30. sys.exit(1)
  31.  
  32. proc_dict = {}
  33. for x in proc.splitlines():
  34. m = re.search('(?P<package>\S+)\W(?P<version>\S+)', x)
  35. proc_dict[m.group('package')] = m.group('version')
  36.  
  37. return proc_dict
  38.  
  39. def uname_list():
  40. '''
  41. Generate a list based on the data from uname, excluding the
  42. system's name.
  43. '''
  44. l = []
  45. l.append(os.uname()[0])
  46. for x in os.uname()[2:]:
  47. l.append(x)
  48.  
  49. return l
  50.  
  51. if __name__ == "__main__":
  52. box_name = os.uname()[1]
  53. # When not using any arguments, defaults to localhost
  54. server = couchdb.client.Server()
  55.  
  56. # Test to see if the db exists, create if it doesn't
  57. try:
  58. db = server['sys_info']
  59. except couchdb.http.ResourceNotFound:
  60. db = server.create('sys_info')
  61.  
  62. # test to see if the computer already exists in the db
  63. try:
  64. rev = db[box_name].rev
  65. db.update([System( _id = box_name, _rev = rev,
  66. uname = uname_list(), packages = get_packages())])
  67. except couchdb.http.ResourceNotFound:
  68. db.save(System(_id = box_name, uname = uname_list(),
  69. packages = get_packages()))

If the script ran without errors then you should be able to this URL and see your computers name as well a value of rev:1 – “some string of characters”. If you click on your computer's name, you'll see all the information the put inserted into the database. What you should see is the “_id” field which will contain the computer's name. A “_rev” field which will say the current revision number for this page. A list of all the packages installed on the system... in no particular order. Finally the output of uname, minus the computer name.
If the script did return some errors, what please make sure that you have module initialization arugments correct (line 54). Couchdb-python uses the defaults if there are no arguments, so in this case the module is going to localhost for the host and the admin account, which has no password. Yes, I know this is really unsafe but I'm just playing with things right now.

One of the things I feel worth pointing out in the System class, in order to create a ListField for CouchDB you must specify what the ListField will contain. In this case (line 16) I am filling the ListField with TextFields. Or in Python speak, filling the list with strings.

I'm surprisingly fascinated with CouchDB... though I'm really hard pressed to say why. At this moment I want to modify my tweet_dump project to use CouchDB. So expect to see that series continued in a little while.

One last thing, for those of you who celebrate it, Happy Thanksgiving!

Syndicate content