<?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>Musings of an Anonymous Geek &#187; Scripting</title>
	<atom:link href="http://www.protocolostomy.com/category/scripting/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.protocolostomy.com</link>
	<description>Made with only the finest 1's and 0's</description>
	<lastBuildDate>Mon, 19 Jul 2010 12:31:02 +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>Wonky Bunny Issue &#8220;Fixed&#8221;</title>
		<link>http://www.protocolostomy.com/2010/07/19/wonky-bunny-issue-fixed/</link>
		<comments>http://www.protocolostomy.com/2010/07/19/wonky-bunny-issue-fixed/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 12:31:02 +0000</pubDate>
		<dc:creator>m0j0</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.protocolostomy.com/?p=819</guid>
		<description><![CDATA[For those who don&#8217;t know what the headline means: Bunny is an open source command line utility written in Python that provides a shell for talking to and testing AMQP brokers (tested on RabbitMQ). AMQP is a queuing protocol. It&#8217;s defined as a binary wire-level protocol as well as a command set. The spec also [...]]]></description>
			<content:encoded><![CDATA[<p>For those who don&#8217;t know what the headline means:</p>
<ol>
<li><a href="http://github.com/bkjones/bunny/">Bunny</a> is an open source command line utility written in Python that provides a shell for talking to and testing AMQP brokers (tested on RabbitMQ).</li>
<li>AMQP is a queuing protocol. It&#8217;s defined as a binary wire-level protocol as well as a command set. The spec also defines a good portion of the server semantics, so by that logic Bunny should work against other AMQP brokers besides RabbitMQ</li>
<li>RabbitMQ is written in Erlang atop OTP, so clustering is &#8216;free and easy&#8217;. My experience with RabbitMQ so far has been fantastic, though I&#8217;d like to see client libraries in general mature a bit further.</li>
</ol>
<p>So, Bunny had this really odd quirk upon its first release. If you did something to cause an error that resulted in a connection being dropped, bunny wouldn&#8217;t trap the error. It would patiently wait for you to enter the next command, and fail miserably. The kicker is that I actually defined a &#8216;check_conn&#8217; method to make sure that the connection was alive before doing anything else, and that really wasn&#8217;t working.</p>
<p>The reason is because py-amqplib (or, perhaps, its interpretation of the AMQP spec, which defines a Connection class), implements a high-level Connection class, along with a Channel class (also defined in the spec), which is what seems to actually map to what you and I as users actually care about: some &#8220;thing&#8221; that lets us communicate with the server, and without which we can&#8217;t talk to the server.</p>
<p>With py-amqplib, a Connection is actually defined as a channel 0, and always channel 0. I gather that channel 0 gets some special treatment in other sections of the library code, and the object that lives at index &#8217;0&#8242; in Connection.channels is actually defined as a Connection object, whereas others are Channel objects.</p>
<p>The result of all of this is that creating a channel in my code and then checking my own object&#8217;s &#8216;chan&#8217; attribute is useless because channels can be dropped on the floor in py-amqplib, and the only way I can tell to figure that out is to check the connection object&#8217;s &#8216;channels&#8217; dictionary. So that&#8217;s what I do now. It seems to be working well.</p>
<p>Not only does bunny now figure out that your connection is gone, but it&#8217;ll also attempt a reconnect using the credentials you gave it in the last &#8216;connect&#8217; command. You see, bunny extends the Python built-in cmd.Cmd object, which lets me define my whole program as a single class. That means that whatever you type in, like the credentials to the &#8216;connect&#8217; command, can be kept handy, since the lifetime of the instance of this class is the same as the lifetime of a bunny session.</p>
<p>So, in summary, bunny is more useful now, but it&#8217;s still not &#8220;done&#8221;. I made this fix over the weekend during an hour I unexpectedly found for myself. It&#8217;s &#8220;a&#8221; solution, but it&#8217;s not &#8220;the&#8221; solution. The real solution is to map out all of the errors that actually cause a connection to drop and give the user a bit more feedback about what happened. I also want to add more features (like support for getting some stats back from Alice to replace bunny&#8217;s really weak &#8216;qlist&#8217; command).</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fwww.protocolostomy.com%2F2010%2F07%2F19%2Fwonky-bunny-issue-fixed%2F';
  addthis_title  = 'Wonky+Bunny+Issue+%26%238220%3BFixed%26%238221%3B';
  addthis_pub    = 'jonesy';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://www.protocolostomy.com/2010/07/19/wonky-bunny-issue-fixed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Date Manipulation</title>
		<link>http://www.protocolostomy.com/2010/07/06/python-date-manipulation/</link>
		<comments>http://www.protocolostomy.com/2010/07/06/python-date-manipulation/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 14:56:33 +0000</pubDate>
		<dc:creator>m0j0</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.protocolostomy.com/?p=781</guid>
		<description><![CDATA[This post is the result of some head-scratching and note taking I did for a reporting project I undertook recently. It&#8217;s not a complete rundown of Python date manipulation, but hopefully the post (and hopefully the comments) will help you and maybe me too The head-scratching is related to the fact that there are several [...]]]></description>
			<content:encoded><![CDATA[<p>This post is the result of some head-scratching and note taking I did for a reporting project I undertook recently. It&#8217;s not a complete rundown of Python date manipulation, but hopefully the post (and hopefully the comments) will help you and maybe me too <img src='http://www.protocolostomy.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The head-scratching is related to the fact that there are several different time-related objects, spread out over a few different time-related modules in Python, and I have found myself in plenty of instances where I needed to mix and match various methods and objects from different modules to get what I needed (which I thought was pretty simple at first glance). Here are a few nits to get started with:</p>
<ul>
<li>strftime/strptime can generate the &#8220;day of week&#8221; where Sunday  is 0, but there&#8217;s no way to tell any of the conversion functions like  gmtime() that you want your week to start on Sunday as far as I know.  I&#8217;m happy to be wrong, so leave comments if I am. It seems odd that you  can do a sort of conversion like this when you output, but not within  the calculation logic.</li>
<li>If you have a struct_time object in localtime format and want to convert  it to an epoch date, time.mktime() works, but if your struct_time  object is in UTC format, you have to use calendar.timegm() &#8212; this is  lame and needs to go away. Just add timegm() to the time module  (possibly renamed?).</li>
<li>time.ctime() will convert an epoch date into nicely formatted local  time, but there&#8217;s no function to provide the equivalent output for UTC  time.</li>
</ul>
<p>There are too many methods and modules for dealing with date  manipulation in Python, such that performing fairly common tasks  requires importing and using a few different modules, different object  types and methods from each. I&#8217;d love this to be cleaned up. I&#8217;d love it  more if I were qualified to do it. More learning probably needs to  happen for that. Anyway, just my $.02.</p>
<h3>Mission 1: Calculating Week Start/End Dates Where Week Starts on Sunday</h3>
<p>My mission: Pull epoch dates from a database. They were generated on a machine whose time does not use UTC, but rather local time (GMT-4).  Given the epoch date, find the start and end of the <em>previous</em> week, where the first day of the week is Sunday, and the last day of the week is Saturday.</p>
<p>So, I need to be able to get a week start/end range, from Sunday at 00:00 through Saturday at 23:59:59. My initial plan of attack was to calculate midnight of the current day, and then base my calculations for Sunday 00:00 on that, using simple timedelta(days=x) manipulations. Then I could do something like calculate the next Sunday and subtract a second to get Saturday at 23:59:59.</p>
<h4>Nothing but &#8216;time&#8217;</h4>
<p>In this iteration, I&#8217;ll try to accomplish my mission using only the &#8216;time&#8217; module and some epoch math.</p>
<p>Seems like you should be able to easily get the epoch value for midnight of the current epoch date, and display it easily with time.ctime(). This isn&#8217;t quite true, however. See here:</p>
<pre>&gt;&gt;&gt; etime = int(time.time())
&gt;&gt;&gt; time.ctime(etime)
'Thu May 20 15:26:40 2010'
&gt;&gt;&gt; etime_midnight = etime - (etime % 86400)
&gt;&gt;&gt; time.ctime(etime_midnight)
'Wed May 19 20:00:00 2010'
&gt;&gt;&gt;
</pre>
<p>The reason this doesn&#8217;t do what you might expect is that time.ctime() in this case outputs the local time, which in this case is UTC-4 (I live near NY, USA, and we&#8217;re currently in DST. The timezone is EDT now, and EST in winter). So when you do math on the raw epoch timestamp (etime), you&#8217;re working with a bare integer that has no idea about time zones. Therefore, you have to account for that. Let&#8217;s try again:</p>
<pre>&gt;&gt;&gt; etime = int(time.time())
&gt;&gt;&gt; etime
1274384049
&gt;&gt;&gt; etime_midnight = (etime - (etime % 86400)) + time.altzone
&gt;&gt;&gt; time.ctime(etime_midnight)
'Thu May 20 00:00:00 2010'
&gt;&gt;&gt;
</pre>
<p>So, why is this necessary? It might be clearer if we throw in a call to gmtime() and also make the math bits more transparent:</p>
<pre>&gt;&gt;&gt; etime
1274384049
&gt;&gt;&gt; time.ctime(etime)
'Thu May 20 15:34:09 2010'
&gt;&gt;&gt; etime % 86400
70449
&gt;&gt;&gt; (etime % 86400) / 3600
19
&gt;&gt;&gt; time.gmtime(etime)
time.struct_time(tm_year=2010, tm_mon=5, tm_mday=20, tm_hour=19, tm_min=34, tm_sec=9, tm_wday=3, tm_yday=140, tm_isdst=0)
&gt;&gt;&gt; midnight = etime - (etime % 86400)
&gt;&gt;&gt; time.gmtime(midnight)
time.struct_time(tm_year=2010, tm_mon=5, tm_mday=20, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=140, tm_isdst=0)
&gt;&gt;&gt; time.ctime(midnight)
'Wed May 19 20:00:00 2010'
&gt;&gt;&gt; time.altzone
14400
&gt;&gt;&gt; time.altzone / 3600
4
&gt;&gt;&gt; midnight = (etime - (etime % 86400)) + time.altzone
&gt;&gt;&gt; time.gmtime(midnight)
time.struct_time(tm_year=2010, tm_mon=5, tm_mday=20, tm_hour=4, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=140, tm_isdst=0)
&gt;&gt;&gt; time.ctime(midnight)
'Thu May 20 00:00:00 2010'
&gt;&gt;&gt;
</pre>
<p>What&#8217;s that now? You want what? You want the epoch timestamp for the previous Sunday at midnight? Well, let&#8217;s see. The time module in Python doesn&#8217;t do deltas per se. You can calculate things out using the epoch bits and some math if you wish. The only bit that&#8217;s really missing is the day of the week our current epoch timestamp lives on.</p>
<pre>&gt;&gt;&gt; time.ctime(midnight)
'Thu May 20 00:00:00 2010'
&gt;&gt;&gt; struct_midnight = time.localtime(midnight)
&gt;&gt;&gt; struct_midnight
time.struct_time(tm_year=2010, tm_mon=5, tm_mday=20, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=140, tm_isdst=1)
&gt;&gt;&gt; dow = struct_midnight.tm_wday
&gt;&gt;&gt; dow
3
&gt;&gt;&gt; midnight_sunday = midnight - ((dow + 1) * 86400)
&gt;&gt;&gt; time.ctime(midnight_sunday)
'Sun May 16 00:00:00 2010'
</pre>
<p>You can do this going forward in time from the epoch time as well. Remember, we also want to grab 23:59:59 on the Saturday after the epoch timestamp you now have:</p>
<pre>&gt;&gt;&gt; saturday_night = midnight + ((5 - dow+1) * 86400) - 1
&gt;&gt;&gt; time.ctime(saturday_night)
'Sat May 22 23:59:59 2010'
&gt;&gt;&gt;
</pre>
<p>And that&#8217;s how you do date manipulation using *only* the time module. Elegant,no?</p>
<p>No. Not really.</p>
<p>Unfortunately, the alternatives also aren&#8217;t the most elegant in the world, imho. So let&#8217;s try doing this all another way, using the datetime module and timedelta objects.</p>
<h4>Now with datetime!</h4>
<p>The documentation for the datetime module says:</p>
<p>&#8220;While date and time arithmetic is supported, the focus of the implementation is on efficient member extraction for output formatting and manipulation.&#8221;</p>
<p>Hm. Sounds a lot like what the time module functions do. Some conversion here or there, but no real arithmetic support. We had to pretty much do it ourselves mucking about with epoch integer values. So what&#8217;s this buy us over the time module?</p>
<p>Let&#8217;s try to do our original task using the datetime module. We&#8217;re going to start with an epoch timestamp, and calculate the values for the previous Sunday at midnight, and the following Saturday at 23:59:59.</p>
<p>The first thing I had a hard time finding was a way to deal with the notion of a &#8220;week&#8221;. I thought I&#8217;d found it in &#8216;date.timetuple()&#8217;, which help(date.timetuple) says is &#8220;compatible with time.localtime()&#8221;. I guess they must mean that the output is the same as time.localtime(), because I can&#8217;t find any other way in which it is similar. Running time.localtime() with no arguments returns a time_struct object for the current time. date.timetuple() requires arguments or it&#8217;ll throw an error, and to make you extra frustrated, the arguments it takes aren&#8217;t in the docs or the help() output.</p>
<p>So maybe they mean it takes the same arguments as time.localtime(), eh? Not so much &#8212; time.localtime() takes an int representing an epoch timestamp. Trying to feed an int to date.timetuple throws an error saying it requires a &#8216;date&#8217; object.</p>
<p>So, the definition of &#8220;compatible&#8221; is a little unclear to me in this context.</p>
<p>So here I&#8217;ve set about finding today, then &#8220;last saturday&#8221;, and then &#8220;the sunday before the last saturday&#8221;:</p>
<pre class="brush: python;">
def get_last_whole_week(today=None):
    # a date object
    date_today = today or datetime.date.today()

    # day 0 is Monday. Sunday is 6.
    dow_today = date_today.weekday()

    if dow_today == 6:
        days_ago_saturday = 1
    else:
    # If day between 0-5, to get last saturday, we need to go to day 0 (Monday), then two more days.
        days_ago_saturday = dow_today + 2

    # Make a timedelta object so we can do date arithmetic.
    delta_saturday = datetime.timedelta(days=days_ago_saturday)

    # saturday is now a date object representing last saturday
    saturday = date_today - delta_saturday

    # timedelta object representing '6 days'...
    delta_prevsunday = datetime.timedelta(days=6)

    # Making a date object. Subtract the days from saturday to get &quot;the Sunday before that&quot;.
    prev_sunday = saturday - delta_prevsunday
</pre>
<p>This gets me date objects representing the start and end time of my reporting range&#8230; sort of. I need them in epoch format, and I need to specifically start at midnight on Sunday and end on 23:59:59 on Saturday night. Sunday at midnight is no problem: timetuple() sets time elements to 0 anyway. For Saturday night, in epoch format, I should probably just calculate a date object for two Sundays a week apart, and subtract one second from one of them to get the last second of the previous Saturday.</p>
<p>Here&#8217;s the above function rewritten to return a tuple containing the start and end dates of the previous week. It can optionally be returned in epoch format, but the default is to return date objects.</p>
<pre class="brush: python;">
def get_last_whole_week(today=None, epoch=False):
    # a date object
    date_today = today or datetime.date.today()
    print &quot;date_today: &quot;, date_today

    # By default day 0 is Monday. Sunday is 6.
    dow_today = date_today.weekday()
    print &quot;dow_today: &quot;, dow_today

    if dow_today == 6:
        days_ago_saturday = 1
    else:
        # If day between 0-5, to get last saturday, we need to go to day 0 (Monday), then two more days.
        days_ago_saturday = dow_today + 2
    print &quot;days_ago_saturday: &quot;, days_ago_saturday
    # Make a timedelta object so we can do date arithmetic.
    delta_saturday = datetime.timedelta(days=days_ago_saturday)
    print &quot;delta_saturday: &quot;, delta_saturday
    # saturday is now a date object representing last saturday
    saturday = date_today - delta_saturday
    print &quot;saturday: &quot;, saturday
    # timedelta object representing '6 days'...
    delta_prevsunday = datetime.timedelta(days=6)
    # Making a date object. Subtract the 6 days from saturday to get &quot;the Sunday before that&quot;.
    prev_sunday = saturday - delta_prevsunday

    # we need to return a range starting with midnight on a Sunday, and ending w/ 23:59:59 on the
    # following Saturday... optionally in epoch format.

    if epoch:
        # saturday is date obj = 'midnight saturday'. We want the last second of the day, not the first.
        saturday_epoch = time.mktime(saturday.timetuple()) + 86399
        prev_sunday_epoch = time.mktime(prev_sunday.timetuple())
        last_week = (prev_sunday_epoch, saturday_epoch)
    else:
        saturday_str = saturday.strftime('%Y-%m-%d')
        prev_sunday_str = prev_sunday.strftime('%Y-%m-%d')
        last_week = (prev_sunday_str, saturday_str)
    return last_week
</pre>
<p>It would be easier to just have some attribute for datetime objects that lets you set the first day of the week to be Sunday instead of Monday. It wouldn&#8217;t completely alleviate every conceivable issue with calculating dates, but it would be a help. The calendar module has a setfirstweekday() method that lets you set the first weekday to whatever you want. I gather this is mostly for formatting output of matrix calendars, but it would be useful if it could be used in date calculations as well. Perhaps I&#8217;ve missed something? Clues welcome.</p>
<h3>Mission 2: Calculate the Prior Month&#8217;s Start and End Dates</h3>
<p>This should be easy. What I hoped would happen is I&#8217;d be able to get today&#8217;s date, and then create a timedelta object for &#8217;1 month&#8217;, and subtract, having Python take care of things like changing the year when the current month is January. Calculating this yourself is a little messy: you can&#8217;t just use &#8220;30 days&#8221; or &#8220;31 days&#8221; as the length of a month, because:</p>
<ol>
<li>&#8220;January 31&#8243; &#8211; &#8220;30 days&#8221; = &#8220;January 1&#8243; &#8212; not the previous month.</li>
<li>&#8220;March 1&#8243; &#8211; &#8220;31 days&#8221; = &#8220;January 30&#8243; &#8212; also not the previous month.</li>
</ol>
<p>Instead, what I did was this:</p>
<ol>
<li>create a datetime object for the first day of the current month (hard coding the &#8216;day&#8217; argument)</li>
<li>used a timedelta object to subtract a day, which gives me a datetime object for the last day of the prior month (with year changed for me if needed),</li>
<li>used that object to create a datetime object for the first day of the prior month (again hardcoding the &#8216;day&#8217; argument)</li>
</ol>
<p>Here&#8217;s some code:</p>
<pre class="brush: python;">
today = datetime.datetime.today()
first_day_current = datetime.datetime(today.year, today.month, 1)
last_day_previous = first_day_current - datetime.timedelta(days=1)
first_day_previous = datetime.datetime(last_day_previous.year, last_day_previous.month, 1)
print 'Today: ', today
print 'First day of this month: ', first_day_current
print 'Last day of last month: ', last_day_previous
print 'First day of last month: ', first_day_previous
</pre>
<p>This outputs:</p>
<pre>Today:  2010-07-06 09:57:33.066446
First day of this month:  2010-07-01 00:00:00
Last day of last month:  2010-06-30 00:00:00
First day of last month:  2010-06-01 00:00:00
</pre>
<p>Not nearly as onerous as the week start/end range calculations, but I kind of thought that between all of these modules we have that one of them would be able to find me the start and end of the previous month. The raw material for creating this is, I suspect, buried somewhere in the source code for the calendar module, which can tell you the start and end dates for a month, but can&#8217;t do any date calculations to give you the previous month. The datetime module can do calculation, but it can&#8217;t tell you the start and end dates for a month. The datetime.timedelta object&#8217;s largest granularity is &#8216;week&#8217; if memory serves, so you can&#8217;t just do &#8216;timedelta(months=1)&#8217;, because the deltas are all converted internally to a <em>fixed number</em> of days, seconds, or milliseconds, and a month isn&#8217;t a fixed number of any of them.</p>
<h3>Converge!</h3>
<p>While I could probably go ahead and use dateutil, which is really darn flexible, I&#8217;d rather be able to do this without a third-party module. Also, dateutil&#8217;s flexibility is not without it&#8217;s complexity, either. It&#8217;s not an insurmountable task to learn, but it&#8217;s not like you can directly transfer your experience with the built-in modules to using dateutil.</p>
<p>I don&#8217;t think merging all of the time-related modules in Python would be necessary or even desirable, really, but I haven&#8217;t thought deeply about it. Perhaps a single module <em>could</em> provide a superclass for the various time-related objects currently spread across three modules, and they could share some base level functionality. Hard to conceive of a timedelta object not floating alone in space in that context, but alas, I&#8217;m thinking out loud. Perhaps a dive into the code is in order.</p>
<p>What have you had trouble doing with dates and times in Python? What docs have I missed? What features are completely missing from Python in terms of time manipulation that would actually be useful enough to warrant inclusion in the collection of included batteries? Let me know your thoughts.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fwww.protocolostomy.com%2F2010%2F07%2F06%2Fpython-date-manipulation%2F';
  addthis_title  = 'Python+Date+Manipulation';
  addthis_pub    = 'jonesy';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://www.protocolostomy.com/2010/07/06/python-date-manipulation/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Brain Fried Over NoSQL</title>
		<link>http://www.protocolostomy.com/2010/06/26/brain-fried-over-nosql/</link>
		<comments>http://www.protocolostomy.com/2010/06/26/brain-fried-over-nosql/#comments</comments>
		<pubDate>Sun, 27 Jun 2010 03:16:02 +0000</pubDate>
		<dc:creator>m0j0</dc:creator>
				<category><![CDATA[Big Ideas]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.protocolostomy.com/?p=799</guid>
		<description><![CDATA[So, I&#8217;m working on a pet project. It&#8217;s in stealth mode. Just kidding &#8212; I don&#8217;t believe in stealth mode It&#8217;s a twitter analytics dashboard that actually does useful things with the mountains of data available from the various Twitter APIs. I&#8217;m writing it in Python using Tornado. Here&#8217;s the first mockup I ever did [...]]]></description>
			<content:encoded><![CDATA[<p>So, I&#8217;m working on a pet project. It&#8217;s in stealth mode. Just kidding &#8212; I don&#8217;t believe in stealth mode <img src='http://www.protocolostomy.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>It&#8217;s a twitter analytics dashboard that actually does useful things with the mountains of data available from the various Twitter APIs. I&#8217;m writing it in Python using Tornado. Here&#8217;s the first mockup I ever did for it, just like 2 nights ago:</p>
<p><a href="http://www.protocolostomy.com/wp-content/uploads/2010/06/tweetdash-mockup.png"><img class="alignleft size-medium wp-image-800" title="mockup" src="http://www.protocolostomy.com/wp-content/uploads/2010/06/tweetdash-mockup-300x214.png" alt="" width="413" height="294" /></a> It&#8217;s already a lot of fun. I&#8217;ve worked with Tornado before and like it a lot. I have most of the base infrastructure questions answered, because this is a pet project and they&#8217;re mostly easy and in some sense &#8220;don&#8217;t matter&#8221;. But that&#8217;s what has me stuck.</p>
<h3>It Doesn&#8217;t Matter</h3>
<p>It&#8217;s true. Past a certain point, belaboring choices of what tools to use where is pointless and is probably premature optimization. I&#8217;ve been working with startups for the past few years, and I&#8217;m painfully aware of what happens when a company takes too long to react to their popularity. I want to architect around that at the start, but I&#8217;m resisting. It&#8217;s a pet project.</p>
<p>But if it doesn&#8217;t matter, that means I can choose tools that are going to be fun to dig into and learn about. I&#8217;ve been so busy writing code to help avoid or buffer impact to the database that I haven&#8217;t played a whole lot with the NoSQL choices out there, and there are tons of them. And they all have a different world view and a unique approach to providing solutions to what I see as somewhat different problems.</p>
<h3>Why NoSQL?</h3>
<p>Why not? I&#8217;ve been working with relational database systems since 1998. I worked on large data reporting projects, a couple of huge data warehousing projects, financial transaction systems, I worked for Sybase as a consulting DBA and project manager for a while, I was into MySQL and PostgreSQL by 2000, used them in production environments starting around 2001-02&#8230; I understand them fairly well. I also understand BDB and other &#8220;flat-file&#8221; databases and object stores. SQLite has become unavoidable in the past few years as well. It&#8217;s not like I don&#8217;t understand the compromises I&#8217;m making going to a NoSQL system.</p>
<p>There&#8217;s a good bit of talk from the RDBMS camp (seriously, why do they need their own camp?) about why NoSQL is bad. Lots of people who know me  would put me in the RDBMS camp, and I&#8217;m telling you not to cry yourself to sleep out of guilt over a desire to get to know these systems. They&#8217;re interesting, and they solve some huge issues surrounding scalability with greater ease than an RDBMS.</p>
<p>Like what? Well, cost for one. If I could afford Oracle I&#8217;d sooner use that than go NoSQL in all likelihood. I can&#8217;t afford it. Not even close. Oracle might as well charge me a small planet for their product. It&#8217;s great stuff, but out of reach. And what about sharding? Sharding a relational database sucks, and to try to hide the fact that it sucks requires you to pile on all kinds of other crap like query proxies, pools, and replication engines, all in an effort to make this beast do something it wasn&#8217;t meant to do: scale beyond a single box. All this stuff also attempts to mask the reality that you&#8217;ve also thrown your hands in the air with respect to at least 2 letters that make up the ACID acronym. What&#8217;s an RDBMS buying you at that point? Complexity.</p>
<p>And there&#8217;s another cost, by the way: no startup I know has the kind of enormous hardware that an enterprise has. They have access to commodity hardware. Pizza boxes. Don&#8217;t even get me started on storage. I&#8217;ve yet to see SSD or flash storage at a startup. I currently work at MyYearbook.com, and there are some pretty hefty database servers there, but it can hardly be called a startup anymore. Hell, they&#8217;re even profitable! <img src='http://www.protocolostomy.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Where Do I Start?</h3>
<p>One nice thing about relationland is I know the landscape pretty well. Going to NoSQL is like dropping me in a country I&#8217;ve never heard of where I don&#8217;t really speak the language. I have some familiarity with key-value stores from dealing with BDB and Memcache, and I&#8217;ve played with MongoDB a bit (using pymongo), but that&#8217;s just the tip of the iceberg.</p>
<p>I heard my boss mention Tokyo Tyrant a few times, so I looked into it. It seems to be one of the more obscure solutions out there from the standpoint of adoption, community, documentation, etc., but it does appear to be very capable on a technical level. However, my application is going to be number-heavy, and I&#8217;m not going to need to own all of the data required to provide the service. I can probably get away with just incrementing counters in Memcache for some of this work. For persistence I need something that will let me do aggregation *FAST* without having to create aggregation tables, ideally. Using a key/value store for counters really just seems like a no-brainer.</p>
<p>That said, I think what I&#8217;ve decided to do, since it doesn&#8217;t matter, is punt on this decision in favor of getting a working application up quickly.</p>
<h3>MySQL</h3>
<p>Yup. I&#8217;m going to pick one or two features of the application to implement as a &#8216;first cut&#8217;, and back them with a MySQL database. I know it well, Tornado has a built-in interface for it, and it&#8217;s not going to be a permanent part of the infrastructure (otherwise I&#8217;d choose PostgreSQL in all likelihood).</p>
<p>To be honest, I don&#8217;t think the challenge in bringing this application to life are really related to the data model or the engine/interface used to access it (though if I&#8217;m lucky that&#8217;ll be a major part of <em>keeping</em> it alive). No, the real problem I&#8217;m faced with is completely unrelated to these considerations&#8230;</p>
<h3>Twitter&#8217;s API Service</h3>
<p>Not the API itself, per se, but the service providing access to it, and the way it&#8217;s administered, is going to be a huge challenge. It&#8217;s not just the Twitter website that&#8217;s inconsistent, the API service goes right along. Not only that, but the type of data I really need to make this application useful isn&#8217;t immediately available from the API as far as I can tell.</p>
<p>Twitter maintains rate limits on the API. You can only make so many calls over so short a period of time. That alone makes providing an application like this to a lot of people a bit of a challenge. Compounding the issue is that, when there are failwhales washing up on the shores, those limits can be dynamically decreased. Ugh.</p>
<p>I guess it&#8217;s not a project for the faint of heart, but it&#8217;ll drive home some golden rules that are easy to neglect in other projects, like planning for failure (of both my application, and Twitter). Also, it&#8217;ll be a lot of fun.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fwww.protocolostomy.com%2F2010%2F06%2F26%2Fbrain-fried-over-nosql%2F';
  addthis_title  = 'Brain+Fried+Over+NoSQL';
  addthis_pub    = 'jonesy';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://www.protocolostomy.com/2010/06/26/brain-fried-over-nosql/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Python IDE Frustration</title>
		<link>http://www.protocolostomy.com/2010/05/13/python-ide-frustration/</link>
		<comments>http://www.protocolostomy.com/2010/05/13/python-ide-frustration/#comments</comments>
		<pubDate>Fri, 14 May 2010 02:22:32 +0000</pubDate>
		<dc:creator>m0j0</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.protocolostomy.com/?p=777</guid>
		<description><![CDATA[I didn&#8217;t think I was looking for a lot in an IDE. Turns out what I want is impossibly hard to find. In the past 6 months I&#8217;ve tried (or tried to try): Komodo Edit Eclipse w/ PyDev PyCharm (from the first EAP build to&#8230; yesterday) Wingware Textmate Wingware First, let&#8217;s get Wingware out of [...]]]></description>
			<content:encoded><![CDATA[<p>I didn&#8217;t think I was looking for a lot in an IDE. Turns out what I want is impossibly hard to find.</p>
<p>In the past 6 months I&#8217;ve tried (or tried to try):</p>
<ul>
<li>Komodo Edit</li>
<li>Eclipse w/ PyDev</li>
<li>PyCharm (from the first EAP build to&#8230; yesterday)</li>
<li>Wingware</li>
<li>Textmate</li>
</ul>
<h3>Wingware</h3>
<p>First, let&#8217;s get Wingware out of the way. I&#8217;m on a Mac, and if you&#8217;re not going to develop for the Mac, I&#8217;m not going to pay you hundreds of dollars for your product. Period. I don&#8217;t even use free software that requires X11. Lemme know when you figure out that coders like Macs and I&#8217;ll try Wingware.</p>
<h3>Komodo Edit</h3>
<p>Well, I wanted to try the IDE but I downloaded it, launched it once for 5 minutes (maybe less), forgot about it, and now my trial is over. I&#8217;ll email sales about this tomorrow. In the meantime, I use Komodo Edit.</p>
<p>Komodo Edit is pretty nice. One thing I like about it is that it doesn&#8217;t really go overboard forcing its world view down my throat. If I&#8217;m working on bunny, which is a one-file Python project I keep in a git repository, I don&#8217;t have to figure out their system for managing projects. I can just &#8220;Open File&#8221; and use it as a text editor.</p>
<p>It has &#8220;ok&#8221; support for Vi key bindings, and it&#8217;s not a plugin: it&#8217;s built in. The support has some annoying limitations, but for about 85% of what I need it to do it&#8217;s fine. One big annoyance is that I can&#8217;t write out a file and assign it a name (e.g. &#8216;:w /some/filename.txt&#8217;). It&#8217;s not supported.</p>
<p>Komodo Edit, unless I missed it, doesn&#8217;t integrate with Git, and doesn&#8217;t offer a Python console. Its capabilities in the area of collaboration in general are weak. I don&#8217;t absolutely have to have them, but things like that are nice for keeping focused and not having to switch away from the window to do anything else, so ideally I could get an IDE that has this. I believe Komodo IDE has these things, so I&#8217;m looking forward to trying it out.</p>
<p>Komodo is pretty quick compared to most IDEs, and has always been rock solid stable for me on both Mac and Linux, so if I&#8217;m not in the mood to use Vim, or I need to work on lots of files at once, Komodo Edit is currently my &#8216;go-to&#8217; IDE.</p>
<h3>PyCharm</h3>
<p>PyCharm doesn&#8217;t have an officially supported release. I&#8217;ve been using Early Adopter Previews since the first one, though. When it&#8217;s finally stable I&#8217;m definitely going to revisit it, because to be honest&#8230; it&#8217;s kinda dreamy.</p>
<p>Git integration is very good. I used it with GitHub without incident for some time, but these are early adopter releases, and things happen: two separate EAP releases of PyCharm made my project files completely disappear without warning, error, or any indication that anything was wrong at all. Of course, this is git, so running &#8216;git checkout -f&#8217; brought things back just fine, but it&#8217;s unsettling, so now I&#8217;m just waiting for the EAP to be over with and I&#8217;ll check it out when it&#8217;s done.</p>
<p>I think for the most part, PyCharm nails it. This is the IDE I want to be using assuming the stability issues are worked out (and I don&#8217;t have reason to believe they won&#8217;t be). It gives me a Python console, VCS integration, a good class and project browser, some nice code analytics, and more complex syntax checking that &#8220;just works&#8221; than I&#8217;ve seen elsewhere. It&#8217;s a pretty handsome, very intuitive IDE, and it leverages an underlying platform whose plugins are available to PyCharm users as well, so my Vim keys are there (and, by the way, the IDEAVim plugin is the most advanced Vim support I&#8217;ve seen in any IDE, hands down).</p>
<h3>Eclipse with PyDev</h3>
<p>One thing I learned from using PyCharm and Eclipse is that where tools like this are concerned, I really prefer a specialized tool to a generic one with plugins layered on to provide the necessary functionality. Eclipse with PyDev really feels to me like a Java IDE that you have to spend time laboriously chiseling, drilling, and hammering to get it to do what you need if you&#8217;re not a Java developer. The configuration is extremely unintuitive, with a profuse array of dialogs, menus, options, options about options and menus, menus about menus and options&#8230; it never seems to end.</p>
<p>All told, I&#8217;ve probably spent the equivalent of 2 working days mucking with Eclipse configuration, and I&#8217;ve only been able to get it &#8220;pretty close&#8221; to where I want it. The Java-loving underpinnings of the Eclipse platform simply cannot be suppressed, while things I had to layer on with plugins don&#8217;t show up in the expected places.</p>
<p>Add to this Eclipse&#8217;s world-view, which reads something like &#8220;there is no filesystem tree: only projects&#8221;, and you have a really damned annoying IDE. I&#8217;ve tried on and off for over a year to make friends with Eclipse because of the good things I hear about PyDev, but it just feels like a big hacky, duct-taped mess to me, and if PyCharm has proven anything to me, it&#8217;s that building a language specific IDE on an underlying platform devoted to Java doesn&#8217;t have to be like this. When I finally got it to some kind of usable point, and after going through the &#8220;fonts and colors&#8221; maze, it turns out the syntax highlighting isn&#8217;t really all that great!</p>
<p>A quick word about Vi key bindings in Eclipse: it&#8217;s not a pretty picture, but the best I&#8217;ve been able to find is a free tool called Vrapper. It&#8217;s not bad. I could get by with Vrapper, but I don&#8217;t believe it&#8217;s as mature and evolved as IDEAVim plugin in PyCharm.</p>
<p>So, I&#8217;ll probably turn back to Eclipse for Java development (I&#8217;m planning on taking on a personal Android project), but I think I&#8217;ve given up on it for anything not Java-related.</p>
<h3>Vim</h3>
<p>Vim is technically &#8216;just an editor&#8217;, but it has some nice benefits, and with the right plugins, it can technically do all of the things a fancy IDE can. I use the taglist plugin to provide the project and class browser functionality, and the kicker here is that you can actually switch to the browser pane, type &#8216;/&#8217; and the object or member you&#8217;re looking for, and jump to it in a flash. It&#8217;s also the most complete Vim key binding implementation available <img src='http://www.protocolostomy.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>The big win for me in using Vim though is remote work. Though I&#8217;d rather do all of my coding locally, there are times when I really have to write code on remote machines, and I don&#8217;t want to go through the rigmarole of coding, pushing my changes, going to my terminal, pulling down the changes, testing, failing, fixing the code on my machine, pushing my changes, pulling my changes&#8230; ugh.</p>
<p>So why not just use Vim? I could do it. I&#8217;ve been using Vim for many years and am pretty good with it, but I just feel like separating my coding from my terminal whenever I can is a good thing. I don&#8217;t want my code to look like my terminal, nor do I want my terminal to look like my IDE theme. I&#8217;m SUPER picky about fonts and colors in my IDE, and I&#8217;m not that picky about them in my terminal. I also want the option of using my mouse while I&#8217;m coding, mostly to scroll, and getting that to work on a Mac in Terminal.app isn&#8217;t as simple as you might expect (and I&#8217;m not a fan of iTerm&#8230; and its ability to do this comes at a cost as well).</p>
<p>MacVim is nice, solves the separation of Terminal and IDE, and I might give it a more serious try, but let&#8217;s face it, it&#8217;s just not an IDE. Code completion is still going to be mediocre, the interface is still going to be terminal-ish&#8230; I just don&#8217;t know. One thing I really love though is the taglist plugin. I think if I could just find a way to embed a Python console along the bottom of MacVim I might be sold.</p>
<p>One thing I absolutely love about Vim, the thing that Vim gets right that none of the IDEs get is colorschemes: MacVim comes with like 20 or 30 colorschemes! And you can download more on the &#8216;net! The other IDEs must lump colorscheme information into the general preferences or something, because you can&#8217;t just download a colorscheme as far as I&#8217;ve seen. The IDE with the worst color/font configuration? Eclipse &#8211; the one all my Python brethren seem to rave about. That is so frustrating. Some day I&#8217;ll make it to PyCon and someone will show me the kool-aid I guess.</p>
<h3>The Frustrating Conclusion</h3>
<p>PyCharm isn&#8217;t soup yet, Wingware is all but ignoring the Mac platform, Eclipse is completely wrong for my brain and I don&#8217;t know how anyone uses it for Python development, Komodo Edit is rock solid but lacking features, and Komodo IDE is fairly pricey and a 30-day trial is always just really annoying (and I kinda doubt it beats PyCharm for Python-specific development). MacVim is a stand-in for a real IDE and it does the job, but I really want more&#8230; integration! I also don&#8217;t like maintaining the plugins and colorschemes and *rc files and ctags, and having to understand its language and all that.</p>
<p>I don&#8217;t cover them here, but I&#8217;ve tried a bunch of the Linux-specific Python IDEs as well, and I didn&#8217;t like a single one of them at all. At some point I&#8217;ll spend more time with those tools to see if I missed something crucial that, once learned, might make it hug my brain like a warm blanket (and make me consider running Linux on my desktop again, something I haven&#8217;t done on a regular ongoing basis in about 4 years).</p>
<p>So&#8230; I don&#8217;t really have an IDE yet. I *did* however just realize that the laptop I&#8217;m typing on right now has never had a Komodo IDE install, so I&#8217;m off to test it now. Wish me luck!</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fwww.protocolostomy.com%2F2010%2F05%2F13%2Fpython-ide-frustration%2F';
  addthis_title  = 'Python+IDE+Frustration';
  addthis_pub    = 'jonesy';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://www.protocolostomy.com/2010/05/13/python-ide-frustration/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
		<item>
		<title>PyTPMOTW: PsycoPG2</title>
		<link>http://www.protocolostomy.com/2010/04/21/pytpmotw-psycopg2/</link>
		<comments>http://www.protocolostomy.com/2010/04/21/pytpmotw-psycopg2/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 01:29:56 +0000</pubDate>
		<dc:creator>m0j0</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[PyTPMOTW]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.protocolostomy.com/?p=761</guid>
		<description><![CDATA[What is this module for? Interacting with a PostgreSQL database in Python. What is PostgreSQL? PostgreSQL is an open source relational database product. It has some more advanced features, like built-in networking-related and GIS-related datatypes, the ability to script stored functions in multiple languages (including Python), etc. If you have never heard of PostgreSQL, get [...]]]></description>
			<content:encoded><![CDATA[<h3>What is this module for?</h3>
<p>Interacting with a PostgreSQL database in Python.</p>
<h3>What is PostgreSQL?</h3>
<p>PostgreSQL is an open source relational database product. It has some more advanced features, like built-in networking-related and GIS-related datatypes, the ability to script stored functions in multiple languages (including Python), etc. If you have never heard of PostgreSQL, get out from under your rock!</p>
<h3>Making Contact</h3>
<p>Using the pscyopg2 module to connect to a PostgreSQL database couldn&#8217;t be simpler. You can use the connect() method of the module, passing in either the individual arguments required to make contact (dbname, user, etc), or you can pass them in as one long &#8220;DSN&#8221; string, like this:</p>
<pre class="brush: python;">
dsn = &quot;host=localhost port=6000 dbname=testdb user=jonesy&quot;
conn = psycopg2.connect(dsn)
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
</pre>
<p>The DSN value is a space-delimited collection of key=value pairs, which I construct before sending the dsn to the psycopg2.connect() method. Once we have a connection object, the very first thing I do is set the connection&#8217;s isolation level to &#8216;autocommit&#8217;, so that INSERT and UPDATE transactions are committed automatically without my having to call conn.commit() after each transaction. There are several isolation levels defined in the psycopg2.extensions package, and they&#8217;re defined in &#8216;extensions&#8217; because they go beyond what is defined in the DB API 2.0 spec that is typically used as a reference in creating Python database modules.</p>
<h3>Simple Queries and Type Conversion</h3>
<p>In order to get anything out of the database, we have to know how to talk to it. Of course this means writing some SQL, but it also means sending query arguments in a format understood by the database. I&#8217;m happy to report that psycopg2 does a pretty good job of making things &#8220;just work&#8221; when it comes to converting your input into PostgreSQL types, and converting the output directly into Python types for easy manipulation in your code. That said, understanding how to properly use these features can be a bit confusing at first, so let me address the source of a lot of early confusion right away:</p>
<pre class="brush: python;">
cur = conn.cursor()
cur.execute(&quot;&quot;&quot;SELECT id, fname, lname, balance FROM accounts WHERE balance &gt; %s&quot;&quot;&quot;, min_balance)
</pre>
<p>Chances are, min_balance is an integer, but we&#8217;re using &#8216;%s&#8217; anyway. Why? Because this isn&#8217;t really you telling Python to do a string formatting operation, it&#8217;s you telling psycopg2 to convert the incoming data using the default psycopg2 method, which converts integers into the PostgreSQL INT type. So, you can use &#8220;%s&#8221; in the &#8216;execute()&#8217; method to properly convert integers, strings, dates, datetimes, timedeltas, lists, tuples and most other native Python types to a corresponding PostgreSQL type. There are adapters built into psycopg2 as well if you need more control over the type conversion process.</p>
<h3>Cursors</h3>
<p>Psycopg2 makes it pretty easy to get your results back in a format that is easy for the receiving code to deal with. For example, the projects I work on tend to use the  RealDictCursor type, because the code tends to require accessing the parts of the resultset rows by name rather than by index (or just via blind looping). Here&#8217;s how to set up and use a RealDictCursor:</p>
<pre class="brush: python;">
curs = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
curs.execute(&quot;SELECT id, name FROM users&quot;)
rs = curs.fetchall()
for row in rs:
   print rs['id'], rs['name']
</pre>
<p>It&#8217;s possible you have two sections of code that&#8217;ll rip apart a result set, and one needs by-name access, and the other just wants to loop blindly or access by index number. If that&#8217;s the case, just replace &#8216;RealDictCursor&#8217; with &#8216;DictCursor&#8217;, and you can have it both ways!</p>
<p>Another nice thing about psycopg2 is the cursor.query attribute and cursor.mogrify method. Mogrify allows you to test and see how a query will look after all input variables are bound, but before the query is sent to the server. Cursor.query prints out the exact query that was actually sent over the wire. I use cursor.query in my logging output all the time to catch out-of-order parameters and mismatched input types, etc. Here&#8217;s an example:</p>
<pre class="brush: python;">
try:
    curs.callproc('myschema.myprocedure', callproc_params)
except Exception as out:
    print out
    print curs.query
</pre>
<h3>Calling Stored Functions</h3>
<p>Stored procedures or &#8216;functions&#8217; in PostgreSQL-speak can be immensely useful in large complex applications where you want to enforce business rules in a single place outside the domain of the main application developers. It can also in some cases be more efficient to put functionality in the database than in the main application code. In addition, if you&#8217;re hiring developers, they should develop in the standard language for your environment, not SQL: SQL should be written by database administrators and developers, and exposed to the developers as needed, so all the developers have to do is call this newly-exposed function. Here&#8217;s how to call a function using psycopg2:</p>
<pre class="brush: python;">
callproc_params = [uname, fname, lname, uid]
cur.callproc(&quot;myschema.myproc&quot;, callproc_params)
</pre>
<p>The first argument to &#8216;callproc()&#8217; is the name of the stored procedure, and the second argument is a sequence holding the input parameters to the function. The input parameters should be in the order that the stored procedure expects them, and I&#8217;ve found after quite a bit of usage that the module typically is able to convert the types perfectly well without my intervention, with one exception&#8230;</p>
<h3>The UUID Array</h3>
<p>PostgreSQL has built-in support for lots of interesting data types, like INET types for supporting IP addresses and CIDR network blocks, and GIS-related data types. In addition, PostgreSQL supports a type that is an array of UUIDs. This comes in handy if you use a UUID to identify items and want to store an array of them to associate with an order, or you use UUIDs to track messages and want to store an array of them together to represent a message thread or conversation. To get a UUID array into the database quickly and easily, it&#8217;s really not too difficult. If you have a list of strings that are UUID strings, you can do a quick conversion, call one function, and then use the array like any other input parameter:</p>
<pre class="brush: python;">
my_uuid_arr = [uuid.UUID(i) for i in my_uuid_arr]
psycopg2.extras.register_uuid()
callproc_params = [
myvar1,
myvar2,
my_uuid_arr
]

curs.callproc('myschema.myproc', callproc_params)
</pre>
<h3>Connection Status</h3>
<p>It&#8217;s not a given that your database connection lives on from query to query, and you shouldn&#8217;t really just assume that because you did a query a fraction of a second ago that it&#8217;s still around now. Actually, to speak about things more Pythonically, you *should* assume the connection is still there, but be ready for failure, and check the connection status to diagnose and help get things back on track. You can check the &#8216;status&#8217; attribute of your connection object. Here&#8217;s one way you might do it:</p>
<pre class="brush: python;">
    @property
    def active_dbconn(self):
        return self.conn.status in [psycopg2.extensions.STATUS_READY, psycopg2.extensions.STATUS_BEGIN]:
</pre>
<p>So, I&#8217;m assuming here that you have some object that has a connection object that it refers to as &#8216;self.connection&#8217;. This one-liner function uses the @property built-in Python decorator, so the other methods in the class can either check the connection status before attempting a query:</p>
<pre class="brush: python;">
if self.active_dbconn:
    try:
        curs.execute(...)
    except Exception as out:
         logging.error(&quot;Houston we have a problem&quot;)
</pre>
<p>Or you can flip that around like this:</p>
<pre class="brush: python;">
try:
   curs.execute(...)
except Exception as out:
    if not self.active_dbconn:
        logging.error(&quot;Execution failed because your connection is dead&quot;)
    else:
         logging.error(&quot;Execution failed in spite of live connection: %s&quot; % out)
</pre>
<h3>Read On&#8230;</h3>
<p>A database is a large, complex beast. There&#8217;s no way to cover the entirety of a database or a module that talks to it in a simple blog post, but I hope I&#8217;ve been able to show some of the more common features, and maybe one or two other items of interest. If you want to know more, I&#8217;m happy to report that, after a LONG time of being unmaintained, the project has recently sprung back to life and is pretty well-documented these days. <a href="http://initd.org/psycopg/docs/index.html">Check it out! </a></p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fwww.protocolostomy.com%2F2010%2F04%2F21%2Fpytpmotw-psycopg2%2F';
  addthis_title  = 'PyTPMOTW%3A+PsycoPG2';
  addthis_pub    = 'jonesy';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://www.protocolostomy.com/2010/04/21/pytpmotw-psycopg2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
