<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Gubatron.com &#187; Python</title>
	<atom:link href="http://www.gubatron.com/blog/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gubatron.com/blog</link>
	<description>Another Venezuelan Geek in New York</description>
	<lastBuildDate>Sun, 18 Jul 2010 17:42:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Using a linear array as a bidimensional matrix</title>
		<link>http://www.gubatron.com/blog/2009/01/27/using-a-linear-array-as-a-bidimensional-matrix/</link>
		<comments>http://www.gubatron.com/blog/2009/01/27/using-a-linear-array-as-a-bidimensional-matrix/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 20:18:12 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[algorithms]]></category>
		<category><![CDATA[arrays]]></category>
		<category><![CDATA[matrix]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[utils]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/?p=1114</guid>
		<description><![CDATA[Often times I find the need to use a list or linear array as if it was a table. Everytime I need to do so, I always end up coding functions to convert a (x,y) coordinate to the real index n in the array. Let me illustrate, with an example. You have a string that [...]]]></description>
			<content:encoded><![CDATA[<p>Often times I find the need to use a list or linear array as if it was a table.</p>
<p>Everytime I need to do so, I always end up coding functions to convert a (x,y) coordinate to the real index n in the array.</p>
<p>Let me illustrate, with an example. You have a string that defines the elements of a game board, and you want to work using (x,y) coordinates.</p>
<pre class="brush: python;">
s=&quot;xxxxx@xx@xxx@@xx&quot;
</pre>
<p>If you were to look at it as a matrix (width=4), it&#8217;d be something like this</p>
<pre class="brush: python;">
s=&quot;xxxx
   x@xx
   @xxx
   @@xx&quot;
</pre>
<p>However, I can&#8217;t do<br />
s[x,y], since it&#8217;s a linear array, it&#8217;s a string.</p>
<p>You need to convert from (x,y) to a number that represents an index in the array.</p>
<p>This is very simple:</p>
<pre class="brush: python;">
width=4
def getNforXY(x,y):
  return x + width*y
</pre>
<p>What if you want to do it backwards. What if you need to know what&#8217;s the X and Y for a given index N in the string?</p>
<pre class="brush: python;">
def getXYforN(n):
  y = int(n/width)
  x = n - width/y
  return (x,y)
</pre>
<p>Cheers</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F&amp;title=Using+a+linear+array+as+a+bidimensional+matrix" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F&amp;title=Using+a+linear+array+as+a+bidimensional+matrix" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F&amp;title=Using+a+linear+array+as+a+bidimensional+matrix" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F&amp;headline=Using+a+linear+array+as+a+bidimensional+matrix" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Using+a+linear+array+as+a+bidimensional+matrix&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Using+a+linear+array+as+a+bidimensional+matrix&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Using+a+linear+array+as+a+bidimensional+matrix&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Using+a+linear+array+as+a+bidimensional+matrix&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Using+a+linear+array+as+a+bidimensional+matrix&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F&amp;title=Using+a+linear+array+as+a+bidimensional+matrix&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2009%2F01%2F27%2Fusing-a-linear-array-as-a-bidimensional-matrix%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2009/01/27/using-a-linear-array-as-a-bidimensional-matrix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Script to Update WordPress in One Step</title>
		<link>http://www.gubatron.com/blog/2008/11/26/python-script-to-update-wordpress-in-one-step/</link>
		<comments>http://www.gubatron.com/blog/2008/11/26/python-script-to-update-wordpress-in-one-step/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 15:23:49 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[one step]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/?p=1015</guid>
		<description><![CDATA[During the past week, I think I had to update all my wordpress instances twice, and it&#8217;s become really annoying doing this manually. I&#8217;ve written a python script which I&#8217;ll share with you. How I keep my wordpress updated by hand I tend to keep my wp-content folder outside of my wordpress installation for 2 [...]]]></description>
			<content:encoded><![CDATA[<p>During the past week, I think I had to update all my wordpress instances twice, and it&#8217;s become really annoying doing this manually. I&#8217;ve written a python script which I&#8217;ll share with you.</p>
<p><strong>How I keep my wordpress updated by hand</strong><br />
I tend to keep my wp-content folder outside of my wordpress installation for 2 reasons:</p>
<p>1. I don&#8217;t like to loose my themes, plugins and customizations<br />
2. I like to keep all my customization changes under subversion</p>
<p>So, if I had my wordpress installation say at:<br />
<strong>/home/user/public_html/blog</strong></p>
<p>I&#8217;d keep my wp-content folder for that here:</p>
<p><strong>/home/user/public_html/wp-content-for-blog</strong></p>
<p>So when I upgrade my blog, I always remove the original wp-content folder that comes along wordpress, and I symlink my hard worked on wp-content folder that lives outside to the freshly unzipped wordpress folder.</p>
<pre class="brush: bash;">
user@machine:~/public_html/blog$ ls -l
...
lrwxrwxr-x 1 user www    54 2008-11-26 09:29 wp-content -&gt; /home/user/public_html/wp-content-for-blog
...
</pre>
<p>So what I endup doing all the time, is downloading the <a href="http://www.wordpress.org/latest.zip" rel="nofollow">latest.zip</a> to ~/public_html/, it will unzip under ~/public_html/wordpress, and then I&#8217;ll copy the current ~/public_html/blog/wp-config.php to ~/public_html/wordpress, then I&#8217;ll remove the default ~/public_html/wordpress/wp-content and symlink the outer wp-content with all my customizations, themes and plugins to it. Once done, I&#8217;ll make a backup of the old wordpress folder, and then I&#8217;ll rename wordpress folder to the name of the blog folder, and it&#8217;s all done.</p>
<p>It&#8217;s simple, but when you have to do it for 5 blogs, every week, it&#8217;s not fun anymore.</p>
<p><strong>The Update Script</strong></p>
<p>So here&#8217;s a script to do it in one step. If you&#8217;re not using my symlinked technique, this will do it for you, you only need to specify the full path to the folder where you want to keep your current wp-content folder outside the new installation before you apply the update, and the name of the folder where your current blog lives. The script below will have its configuration variables towards the beginning set so that they are in line with the example I&#8217;ve been talking about.</p>
<pre class="brush: python;">
#!/usr/bin/python
#########################################################################################
#
# upgrade_wordpress.py - Script to automatically upgrade your wordpress installation.
#
# Requirements:
#   - Python 2.4 or older
#   - WordPress should already be installed
#   - CURL (sudo apt-get install curl)
#
# Author: Angel (Gubatron) Leon
# LICENSE: See the GPL2 license.
# 2008
#########################################################################################
import os

#########################################################################################
#Config (relative to the folder where this script will be run from)
#########################################################################################

#The current folder where the blog lives
BLOG_FOLDER='blog'

#
# The first time you run the script, it will try to make a copy of your
# current wp-content folder outside. Copy here the location of where
# the wp-content folder with your themes and plugins should exist.
#
# After it unzips, it will remove the default wp-content folder from
# the new installation, and it will symlink the external wp-content
# That way you don't ever have to worry about loosing your customizations
# and plugins.
#
WP_CONTENT_OUTSIDE_COPY_FOLDER=&quot;/home/user/public_html/wp-content-for-blog&quot;

#This is where a backup of your current blog will be
BLOG_FOLDER_BACKUP_FOLDER=BLOG_FOLDER+'.old'

#Where to download the wordpress latest.zip from
WORDPRESS_LATEST_ZIP_URL='http://wordpress.org/latest.zip'

#### DO NOT MODIFY AFTER THESE LINES ####

def downloadWordPress(url=WORDPRESS_LATEST_ZIP_URL):
    if os.path.exists('latest.zip'):
        print &quot;Removing old latest.zip&quot;
        os.remove('latest.zip')

    #Try to download with CURL
    print &quot;Attempting to download latest.zip from wordpress.org&quot;
    os.system('curl %s -o latest.zip' % url)

    if not os.path.exists('latest.zip'):
        os.system('wget ' + url)

    return os.path.exists('latest.zip')

def dirExists(dirName):
    return os.path.exists(dirName) and os.path.isdir(dirName)

def backupBlog(currentBlogFolder=BLOG_FOLDER,
               wpContentOriginalFolder=WP_CONTENT_OUTSIDE_COPY_FOLDER,
               backupFolder=BLOG_FOLDER_BACKUP_FOLDER):

    #Remove any previous backups
    if os.path.exists(backupFolder) and os.path.isdir(backupFolder):
        print &quot;Removing previous backup folder&quot;
        os.system('rm -fr ' + backupFolder)

    #Copy the current blog folder into a backup folder just in case.
    #We won't do any database backups for now.
    print &quot;Creating new backup folder&quot;
    os.system('cp -r %s %s' % (currentBlogFolder,backupFolder))

    #Check for the copy of wp-content outside the blog, if it doesn't exist
    #we'll make it for the first time.
    if not dirExists(wpContentOriginalFolder):
        print &quot;Creating outside copy of wp-content&quot;
        os.system('cp -r %s %s' % (os.path.join(currentBlogFolder,'wp-content'),
                                   wpContentOriginalFolder))

    #Copy the latest wp-config.php outside to the current folder
    print &quot;Copying your latest wp-config.php outside&quot;
    os.system('cp %s .' % (os.path.join(currentBlogFolder,'wp-config.php')))

    backupFolderExists = dirExists(backupFolder)
    wpContentFolderExists = dirExists(wpContentOriginalFolder)
    configFileExists = os.path.exists('wp-config.php')

    return backupFolderExists and wpContentOriginalFolder and configFileExists

def upgradeBlog(currentBlogFolder=BLOG_FOLDER,
                backupFolder=BLOG_FOLDER_BACKUP_FOLDER,
                url=WORDPRESS_LATEST_ZIP_URL,
                wpContentOriginalFolder=WP_CONTENT_OUTSIDE_COPY_FOLDER):

    if not downloadWordPress(url):
        print &quot;Could not download latest.zip, aborting.&quot;
        return False

    if not backupBlog(currentBlogFolder,wpContentOriginalFolder,backupFolder):
        print &quot;Could not backup blog or wp-config.ph, aborting.&quot;
        return False

    if currentBlogFolder == 'wordpress':
        print &quot;The current blog folder cannot be 'wordpress, aborting.&quot;
        return False

    #1. If a wordpress/ folder exists, wipe it.
    if dirExists('wordpress'):
        print &quot;Removing old wordpress folder&quot;
        os.system('rm -fr wordpress')

    if dirExists('%s.delete' % currentBlogFolder):
        print &quot;Removing old %s.delete folder&quot; % currentBlogFolder
        os.system('rm -fr %s.delete folder' % currentBlogFolder)

    #2. Unzip new copy
    os.system('unzip latest.zip')

    if not dirExists('wordpress'):
        print &quot;Could not unzip the wordpress installation, aborting.&quot;
        return False

    #1. Copy wp-config.php into the new installation
    os.system('cp wp-config.php wordpress/')

    #2. Remove the default wp-content folder
    os.system('rm -fr wordpress/wp-content')

    #3. Symlink the original wp-content that lives outside
    os.system('ln -s %s wordpress/wp-content' % (wpContentOriginalFolder))

    #4. Verify symlink was created
    if not (os.path.exists('wordpress/wp-content') and os.path.islink('wordpress/wp-content')):
        print &quot;Could not create symlink to wp-content, aborting.&quot;
        return False

    #5. Move original folder to folder.delete, and make this wordpress folder the current folder.
    os.system('mv %s %s.delete' % (currentBlogFolder,currentBlogFolder))

    if not dirExists(currentBlogFolder + &quot;.delete&quot;):
        print &quot;Could not rename current folder for later deletion, aborting.&quot;
        return False

    #6. Rename the new installation as the current blog
    os.system('mv %s %s' % ('wordpress',currentBlogFolder))

    if dirExists('wordpress'):
        print &quot;ALERT: The wordpress folder still exists.&quot;
        return False

    if not dirExists(currentBlogFolder):
        print &quot;ALERT: The blog doesn't exist, recover from the backup folder %s please&quot; % (backupFolder)
        return False

    #7 Cleanup
    os.system('rm -fr %s.delete' % (currentBlogFolder))

    return True

if __name__ == '__main__':
    upgradeBlog()
</pre>
<p><strong>Requirements</strong></p>
<li>shell access to the machine where you have your wordpress installed</li>
<li>a python interpreter installed</li>
<li>curl (sudo apt-get install curl) to download the zip. If you don&#8217;t have it it&#8217;ll attempt to use wget</li>
<p><strong>Installation</strong></p>
<li>Right outside your wordpress installation folder, create a new file called <strong>upgrade_wordpress.py</strong></li>
<li>Copy and paste the script inside that file</li>
<li>Edit the configuration variables to point to the name of your wordpress installation folder, and give it a full path to where you want to keep your wp-content folder (including the name of the folder, so if you want to name it the same way, you could do for example /home/user/wp-content and it&#8217;ll be saved right under your home)</li>
<p><strong>Usage:</strong></p>
<pre class="brush: bash;">python upgrade_wordpress.py</pre>
<p>The script is very fault proof, it will always try to abort in case something is not going the way it&#8217;s expected. At the end of the day it&#8217;ll also leave a backup copy of your current blog in case something goes bad, you can always recover.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F&amp;title=Python+Script+to+Update+Wordpress+in+One+Step" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F&amp;title=Python+Script+to+Update+Wordpress+in+One+Step" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F&amp;title=Python+Script+to+Update+Wordpress+in+One+Step" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F&amp;headline=Python+Script+to+Update+Wordpress+in+One+Step" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Python+Script+to+Update+Wordpress+in+One+Step&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Python+Script+to+Update+Wordpress+in+One+Step&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Python+Script+to+Update+Wordpress+in+One+Step&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Python+Script+to+Update+Wordpress+in+One+Step&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Python+Script+to+Update+Wordpress+in+One+Step&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F&amp;title=Python+Script+to+Update+Wordpress+in+One+Step&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F11%2F26%2Fpython-script-to-update-wordpress-in-one-step%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2008/11/26/python-script-to-update-wordpress-in-one-step/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Script to automatically detect and ban malicious IPs that try to brute force SSH accounts</title>
		<link>http://www.gubatron.com/blog/2008/05/29/script-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts/</link>
		<comments>http://www.gubatron.com/blog/2008/05/29/script-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts/#comments</comments>
		<pubDate>Thu, 29 May 2008 14:01:51 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[automatic banning]]></category>
		<category><![CDATA[ban]]></category>
		<category><![CDATA[banning]]></category>
		<category><![CDATA[brute force]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/?p=816</guid>
		<description><![CDATA[We&#8217;ve noticed that most of our servers have been under heavy attack from random IP addresses to break via SSH. With the help of the last post on how to ban an IP, and the following python script, you&#8217;ll be able to have a cronjob that runs once or twice a day and automagically bans [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve noticed that most of our servers have been under heavy attack from random IP addresses to break via SSH.</p>
<p>With the help of the last post on how to ban an IP, and the following python script, you&#8217;ll be able to have a cronjob that runs once or twice a day and automagically bans all the offending ips from ever trying to brute force their way in ever again.</p>
<p>touch and make executable a file called &#8220;detect_ssh_hostiles&#8221;</p>
<pre>
touch detect_ssh_hostiles
chmod +x detect_ssh_hostiles
</pre>
<p>Then copy the following code inside:</p>
<pre>
# Usage:
# python detect_ssh_hostiles [auth.log file path]
#
# Requirement: There should be "ban_ip" and "unban_ip" command availability on the path
#
# Note: you gotta have read permissions on the auth.log file and sudo
#       permissions for the script to ban the ips.

#If an IP meets this number of failed login attemmpts it will be banned
BAN_THRESHOLD = 7
SUSPECTS = {}

#Put here IP addresses you trust, could be making genuine login errors
SAFE_IPS = ['81.73.111.49','101.73.111.160','72.31.171.235','72.36.23.234','82.36.180.210','202.132.82.16']

import os
import sys
import re

BANNED = {}
def loadBanned():
  '''
  This function will load all the banned IPS into the BANNED Dict.
  It will also count how many times (by mistake) the same IP has
  been banned, and it will unban it, so that it will appear only once.
  '''
  global BANNED
  command = 'sudo iptables --list --numeric'
  try:
    p = os.popen(command,'rb')
  except Exception,e:
    print e
    sys.exit(1)

  line = '-'

  while line != '':
    line = p.readline().strip()

    if line.startswith("DROP"):
      parts = line.split()
      ip = parts[3]

      #add hit or register banned ip
      if BANNED.has_key(ip):
        BANNED[ip]+=1
      else:
        BANNED[ip]=1

  #Make sure banned IPs are banned only once
  for ip in BANNED:
    if BANNED[ip] > 1:
      print "IP %s has been banned %d times" % (ip, BANNED[ip])
      n=BANNED[ip]-1
      while n > 0:
        os.system("unban_ip %s" % ip)
        print ("unban_ip %s" % ip)
        n=n-1

  p.close()

# ---- here we go ----
loadBanned()

#read auth log
logfile = '/var/log/auth.log'

if len(sys.argv)==2:
  logfile = sys.argv[1]

command = 'grep "Failed password for " %s' % logfile
#print command

try:
  p = os.popen(command,'rb')
except Exception,e:
  print e
  sys.exit(1)

line = "123"

while line != '':
  line = p.readline()

  #Sample line:
  # May 25 03:29:49 main sshd[6933]: Failed password for root from 202.118.236.132 port 54863 ssh2
  pattern = "(.*)(from\s)(\d+\.\d+\.\d+\.\d+)(.*)"
  matchObject = re.match(pattern, line)

  suspect = None
  if matchObject is not None:
    suspect = matchObject.groups()[2]

    #skip safe IPs
    if suspect in SAFE_IPS:
      continue

    if SUSPECTS.has_key(suspect):
      #add a hit
      SUSPECTS[suspect] += 1
    else:
      #add first hit
      SUSPECTS[suspect] = 1

p.close() #close the pipe

print "=="*30

import time
t = time.localtime()
#(2008, 6, 6, 9, 35, 21, 4, 158, 1)

timestr = "%d-%d-%d@%d:%d:%d" % (t[0],t[1],t[2],t[3],t[4],t[5])
print timestr
print "--"*30
if len(SUSPECTS) > 0:
  for suspect in SUSPECTS:
    if SUSPECTS[suspect] >= BAN_THRESHOLD and not BANNED.has_key(suspect):
      print "Banning %s with %d attempts" % (suspect,SUSPECTS[suspect])
      BANNED[suspect]=1
      os.system("ban_ip %s" % suspect)
    elif BANNED.has_key(suspect):
      print "Ip %s has already been banned" % (suspect)
    else:
      print "Suspect candidate? %s with %d attempts" % (suspect,SUSPECTS[suspect])
else:
  print "Found no suspects to ban"

print "=="*30</pre>
<p>Then add this as a cronjob of your root user, and it will automatically ban all those IPs that have tried to break in. See the script for configuration. You can always make some IPs immune to banning by adding them on the SAFE_IPS list.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F&amp;title=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F&amp;title=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F&amp;title=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F&amp;headline=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F&amp;title=Script+to+automatically+detect+and+ban+malicious+IPs+that+try+to+brute+force+SSH+accounts&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F05%2F29%2Fscript-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2008/05/29/script-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[Python] PyCon 2008 attendance jumped 70%!</title>
		<link>http://www.gubatron.com/blog/2008/03/28/python-pycon-2008-attendance-jumped-70/</link>
		<comments>http://www.gubatron.com/blog/2008/03/28/python-pycon-2008-attendance-jumped-70/#comments</comments>
		<pubDate>Fri, 28 Mar 2008 13:02:01 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Free Software]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[programmers]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2008/03/28/python-pycon-2008-attendance-jumped-70/</guid>
		<description><![CDATA[Chicago, IL (PRWEB) March 27, 2008 &#8212; PyCon 2008, the annual community conference for Python developers, business leaders, and fans showcased the tremendous increase in growth among the community last week in Chicago. Attendance jumped 70 percent from 2007. Over 1,000 people gathered at the Crowne Plaza Chicago O&#8217;Hare Hotel for PyCon 2008. The influx [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://farm4.static.flickr.com/3236/2336241713_678b94ec11_m.jpg" align="right" style="margin:10px 10px"/> Chicago, IL (PRWEB) March 27, 2008 &#8212; PyCon 2008, the annual community conference for Python developers, business leaders, and fans showcased the tremendous increase in growth among the community last week in Chicago. Attendance jumped 70 percent from 2007.</p>
<p>Over 1,000 people gathered at the Crowne Plaza Chicago O&#8217;Hare Hotel for PyCon 2008. The influx of proposals was so great this year that organizers could only accept half the proposals received, simply due to lack of space. Demand for tutorials, in particular, rose so high that organizers added an extra timeslot full of new sessions. Twenty-five of the 28 tutorials were sold out and there were 22 open source development sprint projects available for attendees to participate in, up from 13 in 2007. More than 270 people took part in the development sprints, which is more than attended the entire first PyCon in 2003.</p>
<p>The best part about PyCon is the people you get to meet<br />
&#8220;As jam-packed as the week&#8217;s events were, a number of attendees and speakers remarked to me that they felt the conference this year was the best yet,&#8221; said PyCon 2008 chair David Goodger. &#8220;It&#8217;s great to see months of work come together and have people really enjoy it.&#8221;</p>
<p>PyCon 2008 is organized and run entirely by volunteers. A true grassroots movement, it is a community conference put on by the community for the community. Many attendees enjoy the numerous sessions, but more importantly, they believe the real value of the conference is the community all being there together.</p>
<p>&#8220;The best part about PyCon is the people you get to meet,&#8221; said Chris McAvoy, founder and president of the Chicago Python Users Group, which hosted PyCon 2008. &#8220;That, coupled with more than 1,000 attendees, compared to the 600 last year, says to me that Python is really building a market here in Chicago and elsewhere. It&#8217;s an exciting time to be a Python developer.&#8221;</p>
<p>PyCon 2009 will also be held in Chicago. For more information about PyCon, please visit <a href="http://us.pycon.org">http://us.pycon.org</a>.</p>
<p><strong>About PyCon</strong></p>
<p>Presented by the Python Software Foundation, the world&#8217;s largest Python conference brings together a diverse group of developers, enthusiasts, and organizations to explore new challenges, launch new businesses and forge new connections within the Python community. PyCon provides attendees with the opportunity to delve into the dynamic programming language employed by well-known companies such as Google, Cisco, and the New York Times. PyCon helps people learn new tools and techniques, showcase projects, and meet other Python fans.</p>
<p>Source: PRWeb.com</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F&amp;title=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F&amp;title=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F&amp;title=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F&amp;headline=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F&amp;title=%5BPython%5D+PyCon+2008+attendance+jumped+70%25%21&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F28%2Fpython-pycon-2008-attendance-jumped-70%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2008/03/28/python-pycon-2008-attendance-jumped-70/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[Python] ip2num / num2ip &#8211; Store an IP string as a 4 byte int.</title>
		<link>http://www.gubatron.com/blog/2008/03/27/python-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int/</link>
		<comments>http://www.gubatron.com/blog/2008/03/27/python-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int/#comments</comments>
		<pubDate>Thu, 27 Mar 2008 16:40:37 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[bytes]]></category>
		<category><![CDATA[ip2num]]></category>
		<category><![CDATA[num2ip]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2008/03/27/python-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int/</guid>
		<description><![CDATA[This is probably everywhere, maybe python also comes with it, but I wanted to have my own implementation, and I&#8217;ll leave it here for future reference. Basically, sometimes you don&#8217;t want to store IPs in Strings cause they take too much space, instead you want to be a good programmer and store them as 4 [...]]]></description>
			<content:encoded><![CDATA[<p>This is probably everywhere, maybe python also comes with it, but I wanted to have my own implementation, and I&#8217;ll leave it here for future reference.</p>
<p>Basically, sometimes you don&#8217;t want to store IPs in Strings cause they take too much space, instead you want to be a good programmer and store them as 4 bytes (IPv4 that is).</p>
<p>So here&#8217;s a couple of functions in python to illustrate the conversion process between string to 4 byte integer, or viceversa:</p>
<pre>
def ip2num(ipString):
    if ipString is None:
        raise Exception("Invalid IP")

    try:
       octets = [octet.strip() for octet in ipString.split('.')]
    except Exception,e:
        raise e

    num = (int(octets[0])<<24) + (int(octets[1])<<16) + (int(octets[2])<<8) + int(octets[3])
    return num

def num2ip(numericIp):
    if numericIp is None or type(numericIp) != int:
        raise Exception("Invalid numeric IP. Must be an integer")
    return str(numericIp >> 24) + '.' + str((numericIp >> 16) &#038; 255) + '.' + str((numericIp >> 8) &#038; 255) + '.' + str(numericIp &#038; 255)
</pre>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F&amp;title=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F&amp;title=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F&amp;title=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F&amp;headline=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int.&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F&amp;title=%5BPython%5D+ip2num+%2F+num2ip+-+Store+an+IP+string+as+a+4+byte+int.&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F03%2F27%2Fpython-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2008/03/27/python-ip2num-num2ip-store-an-ip-string-as-a-4-byte-int/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Checking what PyQt4 version you&#8217;re running</title>
		<link>http://www.gubatron.com/blog/2008/02/01/checking-what-pyqt4-version-youre-running/</link>
		<comments>http://www.gubatron.com/blog/2008/02/01/checking-what-pyqt4-version-youre-running/#comments</comments>
		<pubDate>Sat, 02 Feb 2008 05:33:52 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Qt4]]></category>
		<category><![CDATA[checking]]></category>
		<category><![CDATA[pyqt]]></category>
		<category><![CDATA[pyqt4]]></category>
		<category><![CDATA[reference]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2008/02/01/checking-what-pyqt4-version-youre-running/</guid>
		<description><![CDATA[This is one of those things I tend to forget >>> PyQt4.Qt.qVersion() '4.3.3']]></description>
			<content:encoded><![CDATA[<p>This is one of those things I tend to forget</p>
<p><code><br />
>>> PyQt4.Qt.qVersion()<br />
'4.3.3'<br />
</code></p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F&amp;title=Checking+what+PyQt4+version+you%27re+running" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F&amp;title=Checking+what+PyQt4+version+you%27re+running" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F&amp;title=Checking+what+PyQt4+version+you%27re+running" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F&amp;headline=Checking+what+PyQt4+version+you%27re+running" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Checking+what+PyQt4+version+you%27re+running&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Checking+what+PyQt4+version+you%27re+running&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Checking+what+PyQt4+version+you%27re+running&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Checking+what+PyQt4+version+you%27re+running&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Checking+what+PyQt4+version+you%27re+running&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F&amp;title=Checking+what+PyQt4+version+you%27re+running&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2008%2F02%2F01%2Fchecking-what-pyqt4-version-youre-running%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2008/02/01/checking-what-pyqt4-version-youre-running/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PyQt4: Using QMutex vs QMutexLocker.</title>
		<link>http://www.gubatron.com/blog/2007/11/25/pyqt4-using-qmutex-vs-qmutexlocker/</link>
		<comments>http://www.gubatron.com/blog/2007/11/25/pyqt4-using-qmutex-vs-qmutexlocker/#comments</comments>
		<pubDate>Sun, 25 Nov 2007 23:23:01 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Qt4]]></category>
		<category><![CDATA[python qt4 pyqt3 mutex qmutex qmutexlocker]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2007/11/25/pyqt4-using-qmutex-vs-qmutexlocker/</guid>
		<description><![CDATA[Here&#8217;s some code for my future reference on how to use QMutex or QMutexLocker. Lessons Learned: * Use QMutex to protect data, not code. Try not to lock hughe amounts of code within a function with mutex.lock(), mutex.unlock(), if for any reason you forget to release the lock you&#8217;ll be in trouble. Use the mutex [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s some code for my future reference on how to use QMutex or QMutexLocker.</p>
<p>Lessons Learned:<br />
 * Use QMutex to protect data, not code. Try not to lock hughe amounts of code within a function with mutex.lock(), mutex.unlock(), if for any reason you forget to release the lock you&#8217;ll be in trouble. Use the mutex directly only when you know what it is that you want to protect concurrent access from.<br />
 * When you have a complex function and you don&#8217;t want to worry about what to protect and when to release the lock (on exceptions thrown, before returns,etc), you can create an instance of QMutexLocker and it should release the mutex lock upon destruction&#8230; this takes us to the next lesson<br />
 * When using a QMutexLocker, DO NOT make the QMutexLocker an attribute of your class, otherwise, the reference will live after the method finishes and the lock won&#8217;t be released.</p>
<p>Here&#8217;s some code.</p>
<pre>
from PyQt4.Qt import QObject, QMutex, QApplication, QThread, QMutexLocker
import sys

class MutexTestSubject(QObject):
	'''
	Class that uses a QMutex to synchronize
        access to its add(),substract() methods.

        This works perfectly fine.
	'''
	def __init__(self):
		QObject.__init__(self)
		self.MAX_LIMIT = 100
		self.MIN_LIMIT = 0
		self.counter = 50
		self.mutex = QMutex()

	def add(self):
		self.mutex.lock()
		if self.counter < self.MAX_LIMIT:
			self.counter = self.counter + 1
		self.mutex.unlock()

	def substract(self):
		self.mutex.lock()
		if self.counter > self.MIN_LIMIT:
			self.counter = self.counter - 1
		self.mutex.unlock()

	def printStatus(self,thread):
		print "Counter:",self.counter," - Thread:",id(thread)

		if self.counter > self.MAX_LIMIT+1 or self.counter < self.MIN_LIMIT:
			print "Stopping Threads, Max Surpassed, Not Thread Safe. Last Thread:",id(thread)
			sys.exit()

class MutexLockerTestSubject(QObject):
	'''
	Class that attemps to synchronize thread
 	access to its add(),substract() methods with
	the QMutexLocker object.
	'''
	def __init__(self):
		QObject.__init__(self)
		self.MAX_LIMIT = 100
		self.MIN_LIMIT = 0
		self.counter = 50
		self.mutex = QMutex()

	def add(self):
		#VIP: DO NOT MAKE mutexLocker an attribute of your class.
		#other wise it won't be destroyed and the lock will never be released.
		mutexLocker = QMutexLocker(self.mutex)
		if self.counter < self.MAX_LIMIT:
			self.counter = self.counter + 1

	def substract(self):
		mutexLocker = QMutexLocker(self.mutex)
		if self.counter > self.MIN_LIMIT:
			self.counter = self.counter - 1

	def printStatus(self,thread):
		print "Counter:",self.counter," - Thread:",id(thread)

		if self.counter > self.MAX_LIMIT+1 or self.counter < self.MIN_LIMIT:
			print "Stopping Threads, Max Surpassed, Not Thread Safe. Last Thread:",id(thread)
			sys.exit()

class AdderWorker(QThread):
	def __init__(self, mutexTestObject):
		self.mutexTestObject = mutexTestObject
		QThread.__init__(self)

	def run(self):
		while(True):
			self.mutexTestObject.add()
			self.mutexTestObject.printStatus(self)

class SubstractorWorker(QThread):
	def __init__(self, mutexTestObject):
		self.mutexTestObject = mutexTestObject
		QThread.__init__(self,mutexTestObject)

	def run(self):
		while(True):
			self.mutexTestObject.substract()
			self.mutexTestObject.printStatus(self)

if __name__ == "__main__":
	USE_MUTEX_LOCKER = True #switch this to use regular mutexes vd QMutexLocker
	app = QApplication(sys.argv)
	mutexTestObject = MutexTestSubject() if not USE_MUTEX_LOCKER else MutexLockerTestSubject()

	adderThread  = AdderWorker(mutexTestObject)
	substracterThread = SubstractorWorker(mutexTestObject)

	adderThread.start()
	substracterThread.start()

	sys.exit(app.exec_())
</pre>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F&amp;title=PyQt4%3A+Using+QMutex+vs+QMutexLocker." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F&amp;title=PyQt4%3A+Using+QMutex+vs+QMutexLocker." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F&amp;title=PyQt4%3A+Using+QMutex+vs+QMutexLocker." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F&amp;headline=PyQt4%3A+Using+QMutex+vs+QMutexLocker." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=PyQt4%3A+Using+QMutex+vs+QMutexLocker.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=PyQt4%3A+Using+QMutex+vs+QMutexLocker.&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=PyQt4%3A+Using+QMutex+vs+QMutexLocker.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=PyQt4%3A+Using+QMutex+vs+QMutexLocker.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=PyQt4%3A+Using+QMutex+vs+QMutexLocker.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F&amp;title=PyQt4%3A+Using+QMutex+vs+QMutexLocker.&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F11%2F25%2Fpyqt4-using-qmutex-vs-qmutexlocker%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2007/11/25/pyqt4-using-qmutex-vs-qmutexlocker/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Reference: Binary Operators</title>
		<link>http://www.gubatron.com/blog/2007/07/28/python-reference-binary-operators/</link>
		<comments>http://www.gubatron.com/blog/2007/07/28/python-reference-binary-operators/#comments</comments>
		<pubDate>Sat, 28 Jul 2007 15:43:48 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2007/07/28/python-reference-binary-operators/</guid>
		<description><![CDATA[Python binary operators are pretty much the same as in any other language, however I notice most programmers tend to waste a lot of memory by creating lots and lots of properties say in DB tables, or Objects and using the wrong datatypes. I think its elegant to use the concept of binary flags, for [...]]]></description>
			<content:encoded><![CDATA[<p>Python binary operators are pretty much the same as in any other language, however I notice most programmers tend to waste a lot of memory by creating lots and lots of properties say in DB tables, or Objects and using the wrong datatypes. I think its elegant to use the concept of binary flags, for example, if you have an object that has around 8 or 16 boolean properties, you can store their state in 1 byte or 2 bytes (1 char or 2 char fields), and turn on/off the bits on those fields.</p>
<p>Usually, if you have a binary field, and you want to, turn on bits, toggle bits, and check bits, you do the following.</p>
<p>Suppose &#8220;config&#8221; is an 8 bit number, and you want to modify this bits individually, say config=4 (0b100) and you want to turn on the rightmost bit to have 0b101 (which is a 5) you could do the following</p>
<pre>
>>> #Uses the | operator
... def turnBitOn(config, binaryFlag):
...   return config | binaryFlag
...
>>> config = 4
>>> config = turnBitOn(config,1)
>>> print config
5
</pre>
<p>If you want to check if a Bit is turned on, just use the &#8220;&#038;&#8221; operator, if the result is the same as the bit you&#8217;re comparing, then its turned on.</p>
<pre>
>>> def checkBit(config,binaryFlag):
...   return binaryFlag == config &#038; binaryFlag
...
>>> print checkBit(config,1)
True
>>> print checkBit(config,2) #checks 0b010 in 0b101
False
</pre>
<p>What if you just want to toggle a bit, no matter what&#8217;s in there?<br />
Just use binary XOR, the &#8220;^&#8221; operator.</p>
<pre>
>>> def toggleBit(config,binaryFlag):
...   return config ^ binaryFlag
...
>>> print config
5
>>> config = toggleBit(config,1)
>>> print config
4
>>> config = toggleBit(config,1)
>>> print config
5
</pre>
<p>And now, the last basic operation would be to turn off a bit. For this, you should do a NAND operation. The Binary Not in python as in most programming languages is the &#8220;~&#8221; operator. This is how you can use it to turn off bits.</p>
<p>You have to do it in conjunction with the &#038; operator, sort of doing a NAND</p>
<pre>
>>> 5 &#038; (~1)
4
>>> 5 &#038;~ 1
4
</pre>
<p>So we could define our turnOffBit function as follows:</p>
<pre>
>>> def turnOffBit(config,binaryFlag):
...   return config &#038; (~binaryFlag)
...
>>> print config
5
>>> config = turnOffBit(config,1)
>>> print config
4
>>> config = turnOffBit(config,1)
>>> print config
4
</pre>
<p>Hope this makes a good reference for those trying to make the most out of their bytes.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F&amp;title=Python+Reference%3A+Binary+Operators" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F&amp;title=Python+Reference%3A+Binary+Operators" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F&amp;title=Python+Reference%3A+Binary+Operators" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F&amp;headline=Python+Reference%3A+Binary+Operators" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Python+Reference%3A+Binary+Operators&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Python+Reference%3A+Binary+Operators&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Python+Reference%3A+Binary+Operators&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Python+Reference%3A+Binary+Operators&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Python+Reference%3A+Binary+Operators&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F&amp;title=Python+Reference%3A+Binary+Operators&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F28%2Fpython-reference-binary-operators%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2007/07/28/python-reference-binary-operators/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: How to debug HTTP while using urllib2</title>
		<link>http://www.gubatron.com/blog/2007/07/27/python-how-to-debug-http-while-using-urllib2/</link>
		<comments>http://www.gubatron.com/blog/2007/07/27/python-how-to-debug-http-while-using-urllib2/#comments</comments>
		<pubDate>Fri, 27 Jul 2007 15:36:58 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2007/07/27/python-how-to-debug-http-while-using-urllib2/</guid>
		<description><![CDATA[... import urllib import urllib2 #this is just to prepare a dynamic uri (this is actual code from a system I'm building, sorry) fileDownloadServiceURL = '%s://%s:%s/%s' % (transport,server,port,pathToController) postData = {'URI':fileUri} #add more post stuff here postData = urllib.urlencode(postData) #make sure you encode your post data #add some custom headers if you need them headers={"Host": [...]]]></description>
			<content:encoded><![CDATA[<pre>
...
import urllib
import urllib2

#this is just to prepare a dynamic uri (this is actual code from a system I'm building, sorry)
fileDownloadServiceURL = '%s://%s:%s/%s' % (transport,server,port,pathToController)
postData = {'URI':fileUri} #add more post stuff here
postData = urllib.urlencode(postData) #make sure you encode your post data

#add some custom headers if you need them
headers={"Host": server+':'+port,"Cookie":"JSESSIONID="+sessionId,"User-Agent":"Name of your User-Agent Here"}

#prepare your request, with headers and post data
req = urllib2.Request(fileDownloadServiceURL,postData,headers)

#and this is the magic. Create a HTTPHandler object and put its debug level to 1
httpHandler = urllib2.HTTPHandler()
httpHandler.set_http_debuglevel(1)

#Instead of using urllib2.urlopen, create an opener, and pass the HTTPHandler
#and any other handlers... to it.
opener = urllib2.build_opener(httpHandler)

#User your opener to open the Request.
urlHandle = opener.open(req)

#you'll end up with a file-like object... which I called urlHandle
...
</pre>
<p>The ouput will have useful debugging info about the HTTP connection.</p>
<pre>
connect: (localhost, 8080)
send: u'POST /arcturus-web/fileVariableDownload.service HTTP/1.1\r\nAccept-Encoding: identity\r\nContent-Length: 57\r\nConnection: close\r\nUser-Agent: Temboo Twyla/Arcturus HTTP Downloader\r\nHost: localhost:8080\r\nCookie: JSESSIONID=1b8xl8nozb2i\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n'
send: 'URI=temboo%3A%2F%2Fwww.one.com%2Ffiles.f%2Fmapping1.m.var'
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Language: en-US
header: Content-Type: text/html; charset=ISO-8859-1
header: Connection: close
header: Server: Jetty(6.0.2)
</pre>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F&amp;title=Python%3A+How+to+debug+HTTP+while+using+urllib2" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F&amp;title=Python%3A+How+to+debug+HTTP+while+using+urllib2" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F&amp;title=Python%3A+How+to+debug+HTTP+while+using+urllib2" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F&amp;headline=Python%3A+How+to+debug+HTTP+while+using+urllib2" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Python%3A+How+to+debug+HTTP+while+using+urllib2&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Python%3A+How+to+debug+HTTP+while+using+urllib2&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Python%3A+How+to+debug+HTTP+while+using+urllib2&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Python%3A+How+to+debug+HTTP+while+using+urllib2&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Python%3A+How+to+debug+HTTP+while+using+urllib2&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F&amp;title=Python%3A+How+to+debug+HTTP+while+using+urllib2&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F27%2Fpython-how-to-debug-http-while-using-urllib2%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2007/07/27/python-how-to-debug-http-while-using-urllib2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Note about Signals and PyQt4.</title>
		<link>http://www.gubatron.com/blog/2007/07/09/note-about-signals-and-pyqt4/</link>
		<comments>http://www.gubatron.com/blog/2007/07/09/note-about-signals-and-pyqt4/#comments</comments>
		<pubDate>Mon, 09 Jul 2007 12:35:34 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Qt4]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2007/07/09/note-about-signals-and-pyqt4/</guid>
		<description><![CDATA[I keep making the mistake of sending PyQt_PyObjects instead of sending actual Qt4 objects on signals that are defined by Qt like that. Bottom line: If a signal has been defined by Qt, to send Qt objects, just copy and paste it, do not try to override it by exchanging the Qt objects for PyQt_PyObject. [...]]]></description>
			<content:encoded><![CDATA[<p>I keep making the mistake of sending PyQt_PyObjects instead of sending actual Qt4 objects on signals that are defined by Qt like that.</p>
<p>Bottom line:</p>
<p><strong>If a signal has been defined by Qt, to send Qt objects, just copy and paste it, do not try to override it by exchanging the Qt objects for PyQt_PyObject.</strong></p>
<p>This is because PyQt_PyObject is used to represent regular Python objects, therefore, original Qt4 classes will never emit signals under those weird signatures, Qt4 seems to be very strict on how it matches signals.</p>
<p>So when you see something like this on the documentation:</p>
<pre>
Qt Signals
void currentItemChanged (QTreeWidgetItem *,QTreeWidgetItem *)
</pre>
<p>Define your signal for example like this, and it will work:</p>
<pre>SIGNAL_ITEM_CHANGED = SIGNAL('currentItemChanged (QTreeWidgetItem *,QTreeWidgetItem *)')</pre>
<p>Do not do this, cause it won&#8217;t work:</p>
<pre>SIGNAL_ITEM_CHANGED = SIGNAL('currentItemChanged (PyQt_PyObject, PyQt_PyObject)')</pre>
<p>(Keep in mind PyQt_PyObject is used to represent Python objects only, and its useful only when YOU define and <strong>emit your own signals</strong>)</p>
<p>then connect it from a QTreeWidget item (or derived object) to a listener object&#8217;s method like this:</p>
<pre>QObject.connect(myQTree,SIGNAL_ITEM_CHANGED,myListener.onItemChanged)</pre>
<p>Your object&#8217;s listener method should look like this:</p>
<pre>
def onItemChanged(self, current, previous):
  #do what you gotta do, current and previous will be QTreeWidgetItems
</pre>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F&amp;title=Note+about+Signals+and+PyQt4." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F&amp;title=Note+about+Signals+and+PyQt4." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F&amp;title=Note+about+Signals+and+PyQt4." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F&amp;headline=Note+about+Signals+and+PyQt4." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Note+about+Signals+and+PyQt4.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Note+about+Signals+and+PyQt4.&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Note+about+Signals+and+PyQt4.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Note+about+Signals+and+PyQt4.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Note+about+Signals+and+PyQt4.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F&amp;title=Note+about+Signals+and+PyQt4.&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F07%2F09%2Fnote-about-signals-and-pyqt4%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2007/07/09/note-about-signals-and-pyqt4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to update file timestamps in Python</title>
		<link>http://www.gubatron.com/blog/2007/05/29/how-to-update-file-timestamps-in-python/</link>
		<comments>http://www.gubatron.com/blog/2007/05/29/how-to-update-file-timestamps-in-python/#comments</comments>
		<pubDate>Wed, 30 May 2007 01:06:30 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2007/05/29/how-to-update-file-timestamps-in-python/</guid>
		<description><![CDATA[Sometimes you can be real picky like me about timestamps of files, for example, during my wedding we had a few digital cameras, and one of the cameras had its internal clock 4 hours behind. So what better way for a lazy guy like you to change timestamps than writing a short python script to [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes you can be real picky like me about timestamps of files, for example, during my wedding we had a few digital cameras, and one of the cameras had its internal clock 4 hours behind. So what better way for a lazy guy like you to change timestamps than writing a short python script to fix the problem.</p>
<p><img src="http://farm1.static.flickr.com/199/510507306_179804ba0b.jpg?v=0"/></p>
<p>I wrote this script on the same folder where the pictures with the lagged modification times existed:</p>
<pre>
import os
import time
from stat import *

#returns a list of all the files on the current directory
files = os.listdir('.')

for f in files:
  #my folder has some jpegs and raw images
  if f.lower().endswith('jpg') or f.lower().endswith('crw'):
    st = os.stat(f)
    atime = st[ST_ATIME] #access time
    mtime = st[ST_MTIME] #modification time

    new_mtime = mtime + (4*3600) #new modification time

    #modify the file timestamp
    os.utime(f,(atime,new_mtime))
</pre>
<p>Very nice, I like</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F&amp;title=How+to+update+file+timestamps+in+Python" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F&amp;title=How+to+update+file+timestamps+in+Python" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F&amp;title=How+to+update+file+timestamps+in+Python" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F&amp;headline=How+to+update+file+timestamps+in+Python" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=How+to+update+file+timestamps+in+Python&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=How+to+update+file+timestamps+in+Python&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=How+to+update+file+timestamps+in+Python&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=How+to+update+file+timestamps+in+Python&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=How+to+update+file+timestamps+in+Python&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F&amp;title=How+to+update+file+timestamps+in+Python&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F29%2Fhow-to-update-file-timestamps-in-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2007/05/29/how-to-update-file-timestamps-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recordando algoritmos, Quicksort</title>
		<link>http://www.gubatron.com/blog/2007/05/17/recordando-algoritmos-quicksort/</link>
		<comments>http://www.gubatron.com/blog/2007/05/17/recordando-algoritmos-quicksort/#comments</comments>
		<pubDate>Thu, 17 May 2007 17:36:27 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2007/05/17/recordando-algoritmos-quicksort/</guid>
		<description><![CDATA[Leyendo no se que en internet, lei mencionar algo sobre preguntas de entrevistas de trabajo, y mencionaron que siempre es bueno saber como funciona Quicksort. Por algun motivo, el algoritmo de ordenamiento que siempre recuerdo es Bubble sort, pero todos sabemos que no es el mejor. So decidi repasar y leer como funciona quicksort. Para [...]]]></description>
			<content:encoded><![CDATA[<p>Leyendo no se que en internet, lei mencionar algo sobre preguntas de entrevistas de trabajo, y mencionaron que siempre es bueno saber como funciona Quicksort. Por algun motivo, el algoritmo de ordenamiento que siempre recuerdo es Bubble sort, pero todos sabemos que no es el mejor. So decidi repasar y <a href="http://en.wikipedia.org/wiki/Quicksort">leer como funciona quicksort</a>.</p>
<p>Para los que no recuerdan quicksort es simplemente hacer 3 listas con la lista principal [PRINCIPAL]. Estas listas se generan bajo un criterio bien sencillo. Elige un numero cualquiera del arreglo, la primera lista tendra todos los numeros menores a ese numero [MENORES]. La segunda lista tendra todos los numeros que sean de igual valor a ese numero [IGUALES], y la tercera los mayores [MAYORES].</p>
<p>Una vez que tienes estas 3 listas, el resultado de Quicksort es el siquiente (Donde ++ es concatenar una lista):</p>
<blockquote><p>Quicksort([MENORES]) ++ [IGUALES] ++ Quicksort([MAYORES])</p></blockquote>
<p>Como veras, el algoritmo es recursivo, y llegara el momento que no encuentres numeros menores, iguales o mayores, asi que cuando Quicksort recibe una lista de un solo elemento, devuelve ese elemento.</p>
<p>En python esto sale en 4 lineas con list comprehension, literalmente:</p>
<pre>
def qs(lista):
   if len(lista) <= 1: return lista
   p = lista[0] #el pivote
   return qs([x for x in lista if x < p]) + [x for x in lista if x == p] + qs([x for x in lista if x > p])
</pre>
<p>Pudieras aplicar este algoritmo a cualquier tipo de objeto en Python si para ese objeto defines las funciones de comparacion.<br />
Demasiado arrecho, viva python.</p>
<p>PS: Despues de escribir esto, encontre una implementacion aun mas corta, en la que no utilizan list comprehension, utilizan<br />
funciones lambda, en vez de hacer [x for x in lista if x < pivote] hacen  filter(lambda x,y=pivote: x < y,lista), eso devuelve los elementos que cumplen con la funcion lambda en la lista, es decir   filter(funcion, lista)</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F&amp;title=Recordando+algoritmos%2C+Quicksort" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F&amp;title=Recordando+algoritmos%2C+Quicksort" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F&amp;title=Recordando+algoritmos%2C+Quicksort" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F&amp;headline=Recordando+algoritmos%2C+Quicksort" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Recordando+algoritmos%2C+Quicksort&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Recordando+algoritmos%2C+Quicksort&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Recordando+algoritmos%2C+Quicksort&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Recordando+algoritmos%2C+Quicksort&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Recordando+algoritmos%2C+Quicksort&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F&amp;title=Recordando+algoritmos%2C+Quicksort&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F17%2Frecordando-algoritmos-quicksort%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2007/05/17/recordando-algoritmos-quicksort/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ejemplo de automatizacion entre 2 maquinas remotas con bash scripting y Python</title>
		<link>http://www.gubatron.com/blog/2007/05/10/ejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python/</link>
		<comments>http://www.gubatron.com/blog/2007/05/10/ejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python/#comments</comments>
		<pubDate>Thu, 10 May 2007 14:24:55 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac OSX]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2007/05/10/ejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python/</guid>
		<description><![CDATA[Para los amigos que se inician en el mundo *nix, ya sea con su nueva Mac, o con una PC corriendo Linux, les recomiendo que aprendan a manejar bien los siguientes lenguajes, y el mundo sera suyo: - bash scripting (aliases, variables, exports, iteraciones, condicionales) - python (para programar logica mas compleja y portatil en [...]]]></description>
			<content:encoded><![CDATA[<p>Para los amigos que se inician en el mundo *nix, ya sea con su nueva Mac, o con una PC corriendo Linux,<br />
les recomiendo que aprendan a manejar bien los siguientes lenguajes, y el mundo sera suyo:</p>
<p>- <strong>bash scripting</strong> (aliases, variables, exports, iteraciones, condicionales)<br />
- <strong>python</strong> (para programar logica mas compleja y portatil en cualquier sistema operativo)<br />
- Uso de comandos como grep, egrep, awk (editor de streams) entre otros<br />
- Expresiones regulares</p>
<p>En wedoit4you.com hicimos un simple script que va logeando visitas desde los blogs registrados.<br />
Los blogeros ponen un pedacito de javascript, que al ser invocado, escribe una entrada en un log en el servidor.</p>
<p>Luego tenemos un script que analiza ese log, elimina cualquier intento de hacer muchos clicks, etc. etc.<br />
Ese script se encarga luego de hacer matching de las URLs entrantes, con las URLs de los posts que wedoit4you.com<br />
ya leyo. Este script lamentablemente tarda mucho en analizar mas de 150mb de data, mas lo que haya en el log,<br />
y Dreamhost lo mata si dura mas de un minuto, o si hay mas de N procesos corriendo.</p>
<p>Que hacemos entonces?</p>
<p>Ponemos ese script en una maquina local, donde tenemos todo el cpu, y hacemos que el servidor a ciertas horas<br />
del dia, haga un mysqldump de las tablas que me interesan (BLOGS, BLOG_POSTS, POST_HITS) y meta eso en un archivo<br />
disponible via HTTP.</p>
<p><code><br />
#!/bin/bash<br />
DUMP_DIR=/home/cuenta_en_server/sitio.com/temp/<br />
SQL_FILE_NAME=clicktrackr_dump.sql<br />
SQL_FILE=${DUMP_DIR}/${SQL_FILE_NAME}<br />
TGZ_FILE=${SQL_FILE_FNAME}.tar.gz<br />
mysqldump bd_en_servidor BLOGS BLOG_POSTS POST_HITS > ${SQL_FILE}<br />
cd ${DUMP_DIR}<br />
pwd<br />
echo Making tar<br />
tar cfz ${TGZ_FILE} ${SQL_FILE}<br />
echo Tar with SQL dump ready to be downloaded.<br />
echo Finished.<br />
</code></p>
<p>Este script corre digamos a las 4am en el servidor.</p>
<p><strong>Luego desde la casa</strong><br />
Luego en la maquina local corre un cronjob a las 4:30am, En mi caso una apple iMac Intel, y he aqui el poder de tener una Mac basada en Unix, y no la cagada de windows de mierda.</p>
<p>Hice sencillo bash script que se baja ese dump de la base de datos, y se baja el log del clickTracker para hacer los calculos en mi cpu,<br />
(con el cual hago lo que me da la gana), los calculos son realizados con un script en python (click_tracker.py, incluido al final)<br />
y una vez que termina de calcular, hace ftp de vuelta hacia el servidor y sube un archivo SQL<br />
con instrucciones SQL para que se actualizen los hits de los posts. Este archivo de lolas que no lo subo a un directorio disponible en apache<br />
pq alguien podria meterse con el y alterarnos los hits&#8230; Este Script local luce asi:</p>
<p><code><br />
#!/bin/bash<br />
rm /Users/gubatron/clicktrackr/*.tar.gz<br />
rm /Users/gubatron/clicktrackr/*.sql<br />
rm /Users/gubatron/clicktrackr/*.dat<br />
rm /Users/gubatron/clicktrackr/*.log<br />
echo "Downloading dump from server..."<br />
wget http://www.wedoit4you.com/dir_del_dump/clicktrackr_dump.sql.tar.gz -O /Users/gubatron/clicktrackr/clicktrackr_dump.sql.tar.gz<br />
cd /Users/gubatron/clicktrackr/<br />
echo "Uncompressing Dump..."<br />
tar xfz clicktrackr_dump.sql.tar.gz<br />
echo "Loading data in MySQL"<br />
mysql --user=usuario --password=password --database=bd_local < clicktrackr_dump.sql<br />
echo "Downloading latest tracker.log"<br />
wget http://www.wedoit4you.com/xxxxxxxxx/logs/tracker.log -O /Users/gubatron/clicktrackr/tracker.log<br />
echo "Crunching Data with python script"<br />
python click_tracker.py<br />
echo "Compressing data crunched"<br />
tar cvfz clicktrackr_update_tables.sql.tar.gz clicktrackr_update_tables.sql<br />
echo "Uploading data"<br />
#then upload tar.gz clicktrackr_update_tables.sql<br />
ftp -u ftp://usuario:password@wedoit4you.com/directorioNoAccesiblePorApache/ clicktrackr_update_tables.sql.tar.gz<br />
echo "Finished"<br />
</code></p>
<p>La salida de este script cuando se ejecuta es similar ea esto<br />
<code><br />
imac:~ gubatron$ clicktrackr_processing<br />
Downloading dump from server...<br />
--09:45:14--  http://www.wedoit4you.com/xxxxxxx/clicktrackr_dump.sql.tar.gz<br />
           => `/Users/gubatron/clicktrackr/clicktrackr_dump.sql.tar.gz'<br />
Resolving www.wedoit4you.com... 208.113.146.143<br />
Connecting to www.wedoit4you.com|208.113.146.143|:80... connected.<br />
HTTP request sent, awaiting response... 200 OK<br />
Length: 41,227,814 [application/x-tar]</p>
<p>100%[====================================&gt;] 41,227,814    86.84K/s    ETA 00:00</p>
<p>09:53:18 (83.35 KB/s) - `/Users/gubatron/clicktrackr/clicktrackr_dump.sql.tar.gz' saved [41227814/41227814]</p>
<p>Uncompressing Dump...<br />
Loading data in MySQL<br />
/Users/gubatron/bin/clicktrackr_processing: line 12: clicktrackr_dump.sql: No such file or directory<br />
Downloading latest tracker.log<br />
--09:53:20--  http://www.wedoit4you.com/xxxxxxxxxxxxxx/tracker.log<br />
           =&gt; `/Users/gubatron/clicktrackr/tracker.log'<br />
Resolving www.wedoit4you.com... 208.113.146.143<br />
Connecting to www.wedoit4you.com|208.113.146.143|:80... connected.<br />
HTTP request sent, awaiting response... 200 OK<br />
Length: 3,220 </p>
<p>100%[====================================&gt;] 3,220         --.--K/s             </p>
<p>09:53:23 (33.72 KB/s) - `/Users/gubatron/clicktrackr/tracker.log' saved [3220/3220]</p>
<p>Crunching Data with python script<br />
/Users/gubatron/clicktrackr<br />
No timestamp from last time found.<br />
Loading data from ClickTrackr log...<br />
Saving ClickTrackr data to File...<br />
Saving completed.<br />
Loading Blogs and Last Posts from DB<br />
Saving Blogs to File...<br />
Saving completed.<br />
Loading Posts from DB...<br />
Saving Posts from DB on file<br />
Saving completed.<br />
Crunching data...<br />
0 converted from blog to last post<br />
Didnt find total 11 urls.<br />
Didn't find distinct 11 urls.<br />
Saving crunched data...<br />
Data saved.<br />
Writing SQL...<br />
Finished Writing SQL<br />
Wrote last timestamp.<br />
Compressing data crunched<br />
clicktrackr_update_tables.sql -&gt; clicktrackr_update_tables.sql.tar.gz<br />
Uploading data<br />
Connected to wedoit4you.com.<br />
220 ProFTPD 1.3.0rc2 Server (DreamHost FTP) [208.113.146.143]<br />
331 Password required for wedoit4y.<br />
230 User wedoit4y logged in.<br />
Remote system type is UNIX.<br />
Using binary mode to transfer files.<br />
200 Type set to I<br />
250 CWD command successful<br />
local: clicktrackr_update_tables.sql.tar.gz remote: clicktrackr_update_tables.sql.tar.gz<br />
229 Entering Extended Passive Mode (|||57539|)<br />
150 Opening BINARY mode data connection for clicktrackr_update_tables.sql.tar.gz<br />
100% |*************************************|   550 KB  155.72 KB/s    00:03<br />
226 Transfer complete.<br />
563661 bytes sent in 00:03 (143.48 KB/s)<br />
Finished<br />
</code></p>
<p>Una vez que la data fue procesada y FTPeada al servidor, hay otro cronjob que corre una hora mas<br />
tarde, y este asume que el nuevo archivo con la data procesada estara ahi, podriamos agregarle mas<br />
checks, utilizando "stat" y anotando el ultimo timestamp del sql utlizado la vez anterior cosa que no<br />
volvamos a anotar los hits del dia anterior...</p>
<p>Asi luce el script para actualizar finalmente en el servidor:</p>
<p><code><br />
#!/bin/bash<br />
DIR_PRIVADO=/home/usuario/dirPrivado<br />
PATH_DEL_TRACKER_LOG=/home/usuario/algunaCarpeta/tracker.log<br />
cd ${DIR_PRIVADO}<br />
rm *.sql<br />
tar xvfz clicktrackr_update_tables.sql.tar.gz<br />
mysql bd_en_servidor < ${DIR_PRIVADO}/clicktrackr_update_tables.sql<br />
rm *.tar.gz<br />
rm *.sql<br />
rm<br />
touch ${PATH_DEL_TRACKER_LOG}<br />
chmod 777 ${PATH_DEL_TRACKER_LOG}<br />
</code></p>
<p>Si tienes curiosidad de ver como cruncheo la data localmente, aqui esta el codigo en python.<br />
(Es aun un trabajo en progreso)<br />
<code>
<pre>
#!/home/wedoit4y/bin/python/bin/python2.5
# This is the script that processes the ClickTrackr Log
import os
import sys
import pickle
import time

#NAMES OF FILES WHERE WE'LL STORE THE DIFFERENT STAGES OF RETRIEVED
#AND PROCESSED DATA.

#File that holds a dictionary with URLs and HITs we got from the original log file
FILE_MAX_AGE=3600*1
FILE_TIMESTAMP="clicktrackr_last_timestamp.dat"
FILE_001="clicktrackr_001_url_hits.dat"
FILE_002="clicktrackr_002_blogs_lastposts.dat"
FILE_003="clicktrackr_003_posts_hits.dat"
FILE_004="clicktrackr_004_processed_hits.dat" #...and urls not found
FILE_SQL="clicktrackr_update_tables.sql"

try:
    import snowrss_config
    from snowrss_config import getDbCursor
    #from snowrss import *
except Exception,e:
    print "Could not import snowrss_config [%s]" % e
    sys.exit()

def dbExec(sql):
    """Give it some SQL and it will return the returning cursor"""
    try:
        cursor = getDbCursor()
        cursor.execute(sql)
        cursor.connection.close()
    except Exception, e:
        #MySQL has gone away
        print 'dbExec(%s): ' % unicode(sql)
        print e
        return None
    return cursor

def isFileFresh(fileName):
    """
    Returns True if the file is still good to be used.
    Othewise returns false
    """
    try:
        file_stat = os.stat(fileName)
        file_age = time.time() - file_stat.st_mtime
        if file_age > FILE_MAX_AGE:
            return False
        return True
    except:
        return False

def getData(line):
    """Returns a dict with, IP, Timestamp, URL and User Agent if found

    Parameters
        line - A Line with a ClickTracker log entry

    Output
        {'ip':...,'timestamp':...,'url':....,'ua':...}
        ip-> IP Addres
        time -> Time of the event
        url -> Referer Url
        ua -> User Agent of the rerferer user
    """
    l = line.split()
    result = {}
    result['ip']=l[0]
    result['time']=l[1]
    result['url']=l[2]

    result['ua']='N/A'
    if len(l)>3:
        rest = l[3:]
        ua_name = ''
        for b in rest:
            ua_name = ua_name + ' ' + b
        result['ua'] = ua_name

    return result

#Maximum time to count a click from the same IP on the same URL
TIME_BETWEEN_CLICKS = 12*3600

#On the last run (if finished, we write down the time of the last timestamp on file)
#If we did finish a run, we'll get this number from the timestamp file, and we'll ignore
#all previous log entries to that timestamp.
LAST_TIMESTAMP = None
POSSIBLE_LAST_TIMESTAMP = None

try:
    f = fopen(FILE_TIMESTAMP,"rb")
    LAST_TIMESTAMP = pickle.load(f)
    LAST_TIMESTAMP = long(LAST_TIMESTAMP)
    f.close()
except:
    print "No timestamp from last time found."

urls = {}
urls_not_found = {}
LOG_CLICK_TRACKER='tracker.log'

#check if there is a version of the log file backed that's still good enough to be used.
USABLE_LOG_FILE = LOG_CLICK_TRACKER

#use a copy of the log if we got some pickled data
if isFileFresh(LOG_CLICK_TRACKER + '.last') and isFileFresh(FILE_001):
    USABLE_LOG_FILE = LOG_CLICK_TRACKER + ".last"

IGNORED_ENTRIES = 0
if not isFileFresh(FILE_001):

    #open the tracker log (current or old)
    print "Loading data from ClickTrackr log..."
    f = open(USABLE_LOG_FILE,'r')

    f.seek(0,2)
    eof = f.tell()
    f.seek(0)

    while f.tell() < eof:
        entry = getData(f.readline())

        url = entry['url']
        ip = entry['ip']
        timestamp = entry['time']

        if LAST_TIMESTAMP is not None and long(timestamp) < LAST_TIMESTAMP:
            print "i",
            IGNORED_ENTRIES += 1
            continue

        POSSIBLE_LAST_TIMESTAMP = long(timestamp)

        if not url.startswith('http') or \
           url.startswith('http://babelfish.altavista.com') or \
           url.startswith('http://6'):
            #IGNORED_ENTRIES += 1
            continue

        #Ask if this URL is already there
        if urls.has_key(url):
            #Ask if this IP is already there
            if urls[url].has_key(ip):
                #Get the last time stamp inside this IP
                times = urls[url][ip]
                last_time = times[len(times)-1]
                delta_time = long(timestamp) - long(last_time)
                #If its been more than acceptable time
                if delta_time >= TIME_BETWEEN_CLICKS:
                    urls[url][ip].append(timestamp)

                    hits = 0
                    for ipbuffer in urls[url]:
                        if ipbuffer == 'hits': #just count the keys that are not 'hits'
                            continue
                        hits += len(urls[url][ipbuffer])

                    urls[url]['hits'] = hits
            else:
                urls[url][ip] = [timestamp]
                urls[url]['hits'] = 1
        else:
            urls[url]={}
            urls[url][ip] = [timestamp]
            urls[url]['hits']=1
    f.close()

    urls['POSSIBLE_LAST_TIMESTAMP'] = POSSIBLE_LAST_TIMESTAMP

    #we serialize this data for later
    if IGNORED_ENTRIES > 0:
        print "Ignored %d entries." % IGNORED_ENTRIES

    print "Saving ClickTrackr data to File..."
    f = file(FILE_001,"wb")
    pickle.dump(urls,f)
    f.close()
    print "Saving completed."

    #we make a backup of the current ClickTrackr log (.last), in case we need to run again
    #we can diff with this to know from where to relog in the future
    os.system("cp %s %s" % (LOG_CLICK_TRACKER,LOG_CLICK_TRACKER + ".last"))
else:
    #we unserialize the data
    print "Loading ClickTrackr data from existing file..."
    f = file(FILE_001,"rb")
    urls = pickle.load(f)
    f.close()
    POSSIBLE_LAST_TIMESTAMP = urls.pop('POSSIBLE_LAST_TIMESTAMP') #we popup so we have only urls and we dont modify further down
    print "Loading completed."

#LOAD ALL BLOG POST URLS, IDS AND CURRENT NUMBER OF HITS.
blog_urls = {} #blogs hashed by their urls, Buckets have {'post_id':<last_post_id>,'post_link':<last_post_link>}
blog_ids = {} #blogs hashed by their ids, Buckets have {'post_id':<last_post_id>,'post_link':<last_post_link>}
if not isFileFresh(FILE_002):
    print "Loading Blogs and Last Posts from DB"
    sql = "SELECT Blog_pk_id, Blog_url FROM BLOGS WHERE Blog_active=1;"
    cursor = dbExec(sql)
    results = cursor.fetchall()

    for r in results:
        #Get the ID of the last post on each blog"
        sql = u"SELECT BP_pk_id,BP_link FROM BLOG_POSTS WHERE BP_fk_blog_id = %d ORDER BY BP_pk_id DESC LIMIT 1" % (r['Blog_pk_id']);
        cursor = dbExec(sql)
        last_post = cursor.fetchone()

        if last_post:
            blog_urls[r['Blog_url']] = {'post_id':last_post['BP_pk_id'],'post_link':last_post['BP_link']}
            blog_ids[r['Blog_pk_id']] = {'post_id':last_post['BP_pk_id'],'post_link':last_post['BP_link']}

    #serialize blog_urls and blog_ids
    print "Saving Blogs to File..."
    f = file(FILE_002,"wb")
    pickle.dump(blog_urls,f)
    pickle.dump(blog_ids,f)
    f.close()
    print "Saving completed."
else:
    #load blog_urls from serialized data
    print "Loading Blogs and Last Posts from File..."
    f = file(FILE_002,"rb")
    blog_urls = pickle.load(f)
    blog_ids = pickle.load(f)
    f.close()
    print "Loading completed."

#LOAD ALL BLOG_POSTS URL AND ITS HITS
post_hits = {} #posts hashed by url, Buckets have (post_id, post_hits, blog_id)
if not isFileFresh(FILE_003):
    print "Loading Posts from DB..."
    sql = "SELECT SQL_CACHE BP_link, BP_pk_id, BP_fk_blog_id, PH_hits "
    sql += "FROM BLOG_POSTS LEFT JOIN POST_HITS ON BP_pk_id = PH_fk_post_id;"
    cursor = dbExec(sql)
    results = cursor.fetchall()

    for r in results:
        #hits might be null, if the post has never been reached on our page
        hit_count = int(r['PH_hits']) if r['PH_hits'] is not None else 0
        post_hits[r['BP_link']] = {'post_id':int(r['BP_pk_id']),
                                   'post_hits':hit_count,
                                   'blog_id':r['BP_fk_blog_id']}

    #now get the blog_posts
    print "Saving Posts from DB on file"
    f = file(FILE_003,"wb")
    pickle.dump(post_hits,f)
    f.close()
    print "Saving completed."
else:
    print "Loading Posts from File..."
    f = file(FILE_003,"rb")
    post_hits = pickle.load(f)
    f.close()
    print "Loading completed."

# The stars of the game are:
# - urls {<url>:{'ip':<ip>,'hits':<hits>}} //The urls and how many hits we got from the click trackr log
# - blog_urls {<url>:{'post_id':<last_post_id>,'post_link':<last_post_link>}} //urls of blogs, holding each a tuple with last post info
# - post_hits {<url>:{'post_id':
<post_id>,'post_hits':
<post_hits>,'blog_id':<blog_id>]} //urls and hit info of all posts
# - urls_not_found {'<url>':<no_times_found_in_log>}
if not isFileFresh(FILE_004):
    total_not_found = 0
    distinct_not_found = 0
    total_converted = 0

    converting_blog_url_to_post_url = False

    print "Crunching data..."
    for url in urls:
	#if the current url is the home of a blog
        #we try to see if the blog has any hits.
	if blog_urls.has_key(url):
            url = blog_urls[url]['post_link']
            converting_blog_url_to_post_url = True

        #if you find a direct match add the hits right away
        if post_hits.has_key(url):
	    new_hits = 0
	    if urls.has_key(url) and urls[url].has_key('hits'):
                new_hits = urls[url]['hits']
                if converting_blog_url_to_post_url:
                    total_converted+=1
                    print "!",

            old_hits = 0
            if post_hits[url].has_key('post_hits'):
                old_hits = post_hits[url]['post_hits']

            total_hits = new_hits + old_hits

            #finally update post_hits arrays.
            post_hits[url]['post_hits'] = total_hits
            str_a = "(%(post_id)d):%(post_hits)d:" % post_hits[url]
            str_b = "%d+%d)" % (new_hits,old_hits)
            str_c = str_a + str_b
            print str_c,
        else:
            if urls_not_found.has_key(url):
                urls_not_found[url] += 1
            else:
                urls_not_found[url]=1
                distinct_not_found +=1
            total_not_found += 1
            print "-",

    print
    print "%d converted from blog to last post" % total_converted
    print "Didnt find total %d urls." % total_not_found
    print "Didn't find distinct %d urls." % distinct_not_found

    #serialize processed data in file 4
    print "Saving crunched data..."
    f = file(FILE_004,"wb")
    pickle.dump(post_hits,f)
    pickle.dump(urls_not_found,f)
    f.close()
    print "Data saved."
else:
    print "Loading Previously Crunched Data..."
    f = file(FILE_004,"rb")
    post_hits = pickle.load(f)
    urls_not_found = pickle.load(f)
    f.close
    print "Loading completed."

    #If we can't find it on the blog posts, we could try to
    #slim the URL of this url too http://servername.com/folder
    #and look up on the blog url

    #if nothing, we slim down to http://servername.com

    #if in any of these 2 cases we find a match then
    #we add a hit on the last post of this blog

    #the output of this file should be for now a file with SQL insert statements
print len(post_hits)

#Generate SQL output from post_hits array
# - post_hits {<url>:{'post_id':
<post_id>,'post_hits':
<post_hits>,'blog_id':<blog_id>]}
print "Writing SQL..."
f = file(FILE_SQL,"wb")
for url in post_hits:
    post_id = post_hits[url]['post_id']
    hits = post_hits[url]['post_hits']
    f.writelines("UPDATE POST_HITS SET PH_hits = %d WHERE PH_fk_post_id = %d;\n" % (hits,post_id))
f.close()
print "Finished Writing SQL"

#If we make it all the way till here, we write down the new LAST_TIMESTAMP
if POSSIBLE_LAST_TIMESTAMP is not None:
    f = file(FILE_TIMESTAMP,"wb")
    pickle.dump(POSSIBLE_LAST_TIMESTAMP,f)
    f.close()
    print "Wrote last timestamp."
else:
    print "Did not write LAST timestamp."

for u in urls_not_found:
    print u
</pre>
<p></code></p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F&amp;title=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F&amp;title=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F&amp;title=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F&amp;headline=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F&amp;title=Ejemplo+de+automatizacion+entre+2+maquinas+remotas+con+bash+scripting+y+Python&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F10%2Fejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2007/05/10/ejemplo-de-automatizacion-entre-2-maquinas-remotas-con-bash-scripting-y-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP, ordenando un arreglo de Objetos, y utilizando funciones dentro de funciones.</title>
		<link>http://www.gubatron.com/blog/2007/05/06/php-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones/</link>
		<comments>http://www.gubatron.com/blog/2007/05/06/php-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones/#comments</comments>
		<pubDate>Sun, 06 May 2007 11:10:51 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2007/05/06/php-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones/</guid>
		<description><![CDATA[No fue hasta que programe en Python que me habia pillado que podia definir funciones dentro de funciones en PHP. Hoy tuve que arreglar un defecto en el home de wedoit4you.com del cual algunos bloggers se estaban aprovechando para permanecer en el home. Los articulos aparecen ordenados por fecha de publicacion, y algunos estaban publicando [...]]]></description>
			<content:encoded><![CDATA[<p><center><a href="http://flickr.com/photos/gubatron/486226982/"><img src="http://farm1.static.flickr.com/194/486226982_aa65be1753_o.png" border="0"/></a></center></p>
<p>No fue hasta que programe en Python que me habia pillado que podia definir funciones dentro de funciones en PHP. Hoy tuve que arreglar un defecto en el home de wedoit4you.com del cual algunos bloggers se estaban aprovechando para permanecer en el home. Los articulos aparecen ordenados por fecha de publicacion, y algunos estaban publicando con fechas en el futuro, inclusive abusando y poniendo fechas a fin de mes.</p>
<p>So, en mi clase &#8220;BlogPost&#8221;, puse un metodo &#8220;getTimestamp()&#8221;, si la fecha interna en el objeto esta en el futuro, y no es uno de los blogs a los cuales les paso la gracia&#8230;<br />
Penalizo la fecha del post, y le resto 24 horas a la ultima hora en que se actualizo el Blog.</p>
<p>Pero esto no me resuelve por completo el problema puesto que los posts se leen direct tv de una tabla, y el query ordena por timestamp, el resultado de mi funcion &#8220;getPosts&#8221; es un arreglo de Objetos, y lo ideal era tener esos objetos ordenados dependiendo de la funcion &#8220;getTimestamp()&#8221; en cada objeto &#8220;BlogPost&#8221;</p>
<p>La foto que ven arriba muestra como utilizo la funcion &#8220;usort&#8221; para ordenar (por referencia) el arreglo resultante. La funcion recibe una referencia al arreglo de objetos, y el nombre de una funcion a la cual hacer callback al momento de comparar. La funcion de callback debe recibir 2 objetos como parametro, y luego devolver un numero que represente si el primer parametro es menor o mayor que el segundo parametro. ( < que cero si es menor, cero si son iguales, > que cero si es mayor).</p>
<p>En mi caso llame esta funcion &#8220;cmp&#8221;, pero no la defini afuera de la clase nisiquiera, la defini ahi mismo dentro de la funcion. Si ven la logica de mi funcion el resultado es alrevez puesto que quiero ordenar de manera decrescente.</p>
<p>Espero que alguien haya leido esto si necesita ordenar arreglos.</p>
<p>En cuanto al scoping de las funciones internas, no se que sucederia si hubiese otra funcion llamada igual en el path, supongo que el interprete busca primero en el stack, y encontraria la funcion definida dentro de la funcion actual. Imagino que al terminar de ejecutarse esta funcion, podria no estar diponible para mas nadie. Se que en python puedes hacer Clases dentro de clases, funciones dentro de funciones. En el caso de Clases dentro de Clases, puedes hacer.   Objeto.SubObjeto.metodo(), en el caso de funciones dentro de funciones, creo que no tiene sentido hacer algo como  Objeto.function.subFuncion(), ya que las funciones necesitan parametros, pero seria cuestion de probar a ver, quizas funciona, dado que en python todo es un objeto. Alguien que me eche el cuento para PHP.</p>
<p>(el screenshot fue tomado de emacs en el terminal de OSX Tiger)</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F&amp;title=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F&amp;title=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F&amp;title=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F&amp;headline=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones." ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones.&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones.&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F&amp;title=PHP%2C+ordenando+un+arreglo+de+Objetos%2C+y+utilizando+funciones+dentro+de+funciones.&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F05%2F06%2Fphp-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2007/05/06/php-ordenando-un-arreglos-de-objectos-y-utilizando-funciones-dentro-de-funciones/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Fuck the Python Borg, I like Singleton Better</title>
		<link>http://www.gubatron.com/blog/2007/04/25/fuck-the-python-borg-i-like-singleton-better/</link>
		<comments>http://www.gubatron.com/blog/2007/04/25/fuck-the-python-borg-i-like-singleton-better/#comments</comments>
		<pubDate>Wed, 25 Apr 2007 15:02:50 +0000</pubDate>
		<dc:creator>gubatron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Geeklife]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gubatron.com/blog/2007/04/25/fuck-the-python-borg-i-like-singleton-better/</guid>
		<description><![CDATA[I&#8217;ve read in parts of the web (and on the Martinelli&#8217;s Python Cookbok) that it&#8217;s better to do the Borg pattern over singletons, they say something alongs the lines of: &#8220;who cares about identity, care about shared state&#8221; Coming from the Java world, I just can&#8217;t understand that, why waste memory and cpu to address [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://farm1.static.flickr.com/216/467754686_701bee8596.jpg?v=0" style="margin:3px 3px" alt="I'm looking for a sponsor, HÃ¤agen-Dazs wants a geek??"></p>
<p>I&#8217;ve read in parts of the web (and on the Martinelli&#8217;s Python Cookbok) that it&#8217;s better to do the Borg pattern over singletons, they say something alongs the lines of:</p>
<p><strong>&#8220;who cares about identity, care about shared state&#8221;</strong></p>
<p>Coming from the Java world, I just can&#8217;t understand that, why waste memory and cpu to address objects that share a state when you can have a single object in memory.</p>
<p>If you&#8217;re looking on how to implement singleton in a simple manner with Python, do the following my friend:</p>
<pre style="width:400px; border:none; font-weight:bolder">
class MyClass:
  __INSTANCE__ = None

  def __init__(self):
    #do whatever you need on your constructor
    pass

  @staticmethod
  def getInstance():
    if MyClass.__INSTANCE__ is None:
      MyClass.__INSTANCE__ = MyClass()
    return MyClass.__INSTANCE__

#Then use it.
theOne = MyClass.getInstance()
</pre>
<p>Done deal, now start trolling on why this code sucks so we can fix it.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F&amp;title=Fuck+the+Python+Borg%2C+I+like+Singleton+Better" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F&amp;title=Fuck+the+Python+Borg%2C+I+like+Singleton+Better" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F&amp;title=Fuck+the+Python+Borg%2C+I+like+Singleton+Better" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F&amp;headline=Fuck+the+Python+Borg%2C+I+like+Singleton+Better" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Fuck+the+Python+Borg%2C+I+like+Singleton+Better&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Fuck+the+Python+Borg%2C+I+like+Singleton+Better&amp;u=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Fuck+the+Python+Borg%2C+I+like+Singleton+Better&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Fuck+the+Python+Borg%2C+I+like+Singleton+Better&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Fuck+the+Python+Borg%2C+I+like+Singleton+Better&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F&amp;title=Fuck+the+Python+Borg%2C+I+like+Singleton+Better&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.gubatron.com%2Fblog%2F2007%2F04%2F25%2Ffuck-the-python-borg-i-like-singleton-better%2F" ><img class="lightsocial_img" src="http://www.gubatron.com/blog/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.gubatron.com/blog/2007/04/25/fuck-the-python-borg-i-like-singleton-better/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->