<?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>Eric Wendelin&#039;s Blog &#187; Python</title>
	<atom:link href="http://eriwen.com/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://eriwen.com</link>
	<description>Programming productively with open-source tools</description>
	<lastBuildDate>Tue, 31 Jan 2012 14:30:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Griffon, meet Jython</title>
		<link>http://eriwen.com/python/griffon-jython-plugin/</link>
		<comments>http://eriwen.com/python/griffon-jython-plugin/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 10:00:50 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Griffon]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Project]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=1132</guid>
		<description><![CDATA[I've come to love the <a href="http://python.org/">Python</a> language for its elegant syntax combined with powerful constructs like comprehensions. <a href="http://jython.org/">Jython</a> allows me to take Python to the next level by allowing it to interact with my existing JVM-compatible code. Now I want to extend that even further and allow myself (and you, of course) to integrate Jython with <a href="http://griffon.codehaus.org/">Griffon</a>, a framework for building desktop applications in <a href="http://groovy.codehaus.org/">Groovy</a>.

<h2>Introducing the Jython plugin for Griffon</h2>
The Jython plugin enables compiling and running Jython code on your Griffon application. You don't even need to install Jython manually. A Jython REPL is available with access to your Groovy/Java classes
 <a href="http://eriwen.com/python/griffon-jython-plugin/">Continue reading <span class="meta-nav">&#8594;</span></a>


Related posts:<ol><li><a href='http://eriwen.com/interview/andres-almiray/' rel='bookmark' title='Interview with Andres Almiray'>Interview with Andres Almiray</a></li>
<li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Python first impressions'>Python first impressions</a></li>
<li><a href='http://eriwen.com/groovy/groovy-categories/' rel='bookmark' title='Using Groovy Categories to override operators'>Using Groovy Categories to override operators</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve come to love the <a href="http://python.org/">Python</a> language for its elegant syntax combined with powerful constructs like comprehensions. <a href="http://jython.org/">Jython</a> allows me to take Python to the next level by allowing it to interact with my existing JVM-compatible code. Now I want to extend that even further and allow myself (and you, of course) to integrate Jython with <a href="http://griffon.codehaus.org/">Griffon</a>, a framework for building desktop applications in <a href="http://groovy.codehaus.org/">Groovy</a>.</p>
<h2>Introducing the Jython plugin for Griffon</h2>
<p>The Jython plugin enables compiling and running Jython code on your Griffon application. You don&#8217;t even need to install Jython manually. A Jython REPL is available with access to your Groovy/Java classes if you use:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
griffon jython-repl
</pre>
<p>You can even load Jython scripts on-the-fly by putting them in <code>MyGriffonApp/griffon-app/resources/jython</code>!</p>
<p>In the rest of the article, we are going to create a simple application that mixes Griffon and Jython using the Griffon-Jython plugin.</p>
<p><img src="http://static.eriwen.com/images/jython-sample.png" alt="Jython Sample Application" /></p>
<h2>Getting started with griffon-jython</h2>
<p>It&#8217;s easy to setup Griffon, and you&#8217;ll find <a href="http://griffon.codehaus.org/Installing+Griffon" title="Installing Griffon">instructions here</a> and <a href="http://griffon.codehaus.org/Download" title="Griffon downloads">downloads here</a>. Once you&#8217;re done, you can create a Griffon app and install the jython plugin by typing:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
griffon create-app MyGriffonApp
# Go into MyGriffonApp directory
cd !$
# Download and install the latest Jython plugin!
griffon install-plugin jython
</pre>
<p>Now that we&#8217;ve installed the Jython plugin, you can create a Jython class on your command-line:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
griffon create-jython-class com.mypkg.MyJythonClass
</pre>
<p>Let&#8217;s create a Jython class that greets the user when a button is clicked.</p>
<pre class="brush: python; light: true; title: ; notranslate">
from com.mypkg import IGreeter

class MyJythonClass(IGreeter):
  def __init__(self):
    pass

  def greet(self, who, model):
    greeting = 'Hello %s from Jython!' % str(who)
    model.setOutput(greeting)
</pre>
<p>Jython classes are exposed to Griffon using an <a href="http://en.wikipedia.org/wiki/Factory_method_pattern">Object Factory Pattern</a> as suggested in the <a href="http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html#using-jython-within-java-applications" title="Using Jython Within Java Applications">Definitive Guide To Jython, Chapter 10</a>. Therefore, we create a Java (well, Groovy) interface that <code>MyJythonClass</code> will extend to allow Griffon to get at the proper method implementations. It sounds rather complicated, but it really is quite simple. Let&#8217;s create the <code>IGreeter</code> interface to show you what I&#8217;m talking about:</p>
<pre class="brush: groovy; light: true; title: ; notranslate">
package com.mypkg

public interface IGreeter {
  // Same signature as our Jython method
  public void greet(String greetee, def model)
}
</pre>
<p>Our <code>greet()</code> method accepts a <code>String</code> (the textField input) and a model of unspecified type.</p>
<p>Griffon auto-generates MVC classes for you, so we can use those. You&#8217;ll find them in the <code>MyGriffonApp/griffon-app/{models,views,controllers}</code> directories. We are going to change those for our app! Here is the aforementioned <code>Model</code>:</p>
<pre class="brush: groovy; light: true; title: ; notranslate">
package com.mypkg
import groovy.beans.Bindable

class MyGriffonAppModel {
    @Bindable String input = ''
    @Bindable String output = ''
}
</pre>
<p>Groovy implicitly creates <code>get/setInput()</code> methods and allows them to be bound (to the View textField value, e.g.). Here is that <code>MyGriffonAppView</code>:</p>
<pre class="brush: groovy; light: true; title: ; notranslate">
package com.mypkg

application(title:'Griffon Jython Sample', pack:true, locationByPlatform:true) {
  gridLayout(cols: 1, rows: 2)
  //Note the ID on this textField
  textField(id: &quot;input&quot;, columns: 20)
  button(&quot;Click me!&quot;, actionPerformed: controller.handleClick)
  bean(model, input: bind {input.text})
}
</pre>
<p>Finally, the most critical part of our application that will interact with our Jython class, the <code>MyGriffonAppController</code>:</p>
<pre class="brush: groovy; light: true; title: ; notranslate">
package com.mypkg

import java.beans.PropertyChangeListener
import griffon.jython.JythonObjectFactory
import javax.swing.JOptionPane

class MyGriffonAppController {
  // Values auto-injected
  def model
  def view
  def greeter

  def mvcGroupInit(Map args) {
     // When our model output has changed, show a dialog
     model.addPropertyChangeListener(&quot;output&quot;, { evt -&gt;
       if(!evt.newValue) return
       doLater {
         JOptionPane.showMessageDialog(app.windowManager.windows[0],
           evt.newValue, &quot;Message from Jython&quot;, JOptionPane.INFORMATION_MESSAGE)
       }
     } as PropertyChangeListener)

     // Instantiate MyJythonClass
     JythonObjectFactory factory =
         new JythonObjectFactory(IGreeter.class, 'MyJythonClass', 'MyJythonClass')
     greeter = (IGreeter) factory.createObject()
   }

  def handleClick = { evt = null -&gt;
    if(!model.input) return
    model.output = &quot;&quot;
    // invoke Jython class (outside EDT)
    doOutside {
      greeter.greet(model.input, model)
    }
  }
}
</pre>
<p>There you have it! Now we can utilize such Jython greatness as <a href="http://wiki.python.org/moin/Generators" title="Python generators">generators</a> and <a href="http://diveintopython.org/power_of_introspection/filtering_lists.html">list comprehensions</a>!</p>
<h2>Further reading</h2>
<p>The <a href="http://dist.codehaus.org/griffon/guide/index.html">Griffon Guide</a> is the best place to go for Griffon documentation. You can find more comprehensive documentation for the Jython plugin on the <a href="http://griffon.codehaus.org/Jython+Plugin" title="Griffon - Jython Plugin">official plugin page</a>. As always, this stuff is completely open-source, and you can find all of the code and submit suggestions and issues at the <a href="https://github.com/eriwen/griffon-jython" title="griffon-jython source code repo">GitHub repository</a>. </p>


<p>Related posts:<ol><li><a href='http://eriwen.com/interview/andres-almiray/' rel='bookmark' title='Interview with Andres Almiray'>Interview with Andres Almiray</a></li>
<li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Python first impressions'>Python first impressions</a></li>
<li><a href='http://eriwen.com/groovy/groovy-categories/' rel='bookmark' title='Using Groovy Categories to override operators'>Using Groovy Categories to override operators</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/python/griffon-jython-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Python to update your FeedBurner stats</title>
		<link>http://eriwen.com/python/update-feedburner-count/</link>
		<comments>http://eriwen.com/python/update-feedburner-count/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 11:00:11 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Project]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=986</guid>
		<description><![CDATA[<img src="http://eriwen-cdn.s3.amazonaws.com/images/html.jpg" style="margin: 0 8px 0 0; float: left;"/>Ever since I've moved to my own server for my websites, I've wanted to reduce the number of HTTP requests per user as much as possible. Here is how I (and you) can use Python to shave 1 more request off that number.

I can do this (and remove a <abbr title="Domain Name Service">DNS</abbr> lookup) by updating my <a href="http://feedburner.google.com">Feedburner</a> count using an automated <strong>script on my server instead of having each client request it.</strong> 

<h2>Using the FeedBurner Awareness API</h2>
Most of the time you only care about getting your total subscribers at the moment. The <a href="http://code.google.com/apis/feedburner/awareness_api.html">FeedBurner Awareness API</a> is far more capable than just doing that, but we're going to keep it simple today. 
 <a href="http://eriwen.com/python/update-feedburner-count/">Continue reading <span class="meta-nav">&#8594;</span></a>


Related posts:<ol><li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Python first impressions'>Python first impressions</a></li>
<li><a href='http://eriwen.com/python/site-monitor/' rel='bookmark' title='Site monitoring with Python and cron'>Site monitoring with Python and cron</a></li>
<li><a href='http://eriwen.com/javascript/stacktrace-update/' rel='bookmark' title='Javascript Stacktrace update'>Javascript Stacktrace update</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://eriwen-cdn.s3.amazonaws.com/images/html.jpg" style="margin: 0 8px 0 0; float: left;"/>Ever since I&#8217;ve moved to my own server for my websites, I&#8217;ve wanted to reduce the number of HTTP requests per user as much as possible. Here is how I (and you) can use Python to <strong>shave 1 more request off that number.</strong></p>
<p>I can do this (and remove a <abbr title="Domain Name Service">DNS</abbr> lookup) by updating my <a href="http://feedburner.google.com">Feedburner</a> count using an automated <strong>script on my server instead of having each client request it.</strong> </p>
<h2>Using the FeedBurner Awareness API</h2>
<p>Most of the time you only care about getting your total subscribers at the moment. The <a href="http://code.google.com/apis/feedburner/awareness_api.html">FeedBurner Awareness API</a> is far more capable than just doing that, but we&#8217;re going to keep it simple today. </p>
<p>For the simple case you just need your feed ID or URI. Try:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
curl -s 'https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=YOUR_FEED_NAME'
</pre>
<p>You receive an XML response like:</p>
<pre class="brush: xml; light: true; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;rsp stat=&quot;ok&quot;&gt;
  &lt;!--This information is part of the FeedBurner Awareness API. If you want to hide this information, you may do so via your FeedBurner Account.--&gt;
  &lt;feed id=&quot;foo0nbta7tscktjrgddc95gg3s&quot; uri=&quot;EricWendelin&quot;&gt;
    &lt;entry date=&quot;2009-11-03&quot; circulation=&quot;1181&quot; hits=&quot;3901&quot; reach=&quot;21&quot; /&gt;
  &lt;/feed&gt;
&lt;/rsp&gt;
</pre>
<p>Now we just need to parse out the &#8220;circulation&#8221; which is your subscriber count. </p>
<h2>Quick and dirty bash script</h2>
<p>This is what I used to use until FeedBurner started returning 0s or blanks in the XML returned: </p>
<pre class="brush: bash; light: true; title: ; wrap-lines: false; notranslate">
#!/bin/bash
FEED_COUNT=`curl -s https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=EricWendelin | egrep -o circulation=\&amp;quot;[0-9]+\&amp;quot; | egrep -o [0-9]+`

sed -r -i &amp;quot;s/(\&amp;quot;numsubscribers\&amp;quot;&amp;gt;)[^&amp;lt;]+&amp;lt;/\1$FEED_COUNT&amp;lt;/g&amp;quot; /my/path/to/sidebar.php

echo $FEED_COUNT
</pre>
<p>You can <a href="http://eriwen.com/productivity/crontab-for-automation/">use cron</a> to replace some HTML, log the count, etc. every so often. </p>
<h2>The Python</h2>
<p>The Python version is much lengthier but has error checking and does not have to do file-replacement. The following is also <a href="http://gist.github.com/226407">available on GitHub</a> for your extending pleasure ;).</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/env python

# Usage: ./check_feedburner.py MyFeedName

import re, sys, urllib, fileinput
from xml.dom import minidom

API_URL = 'https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=%s'
# To replace the feed count in a file, put it here
FEED_COUNT_FILE = '/path/to/your/file.php'
# HTML to replace with feed count - REPLACE ME
HTML_REGEX = r'(&amp;quot;numsubscribers&amp;quot;&amp;gt;)[^&amp;lt;]+&amp;lt;'
REPLACE_STRING = r'&amp;quot;numsubscribers&amp;quot;&amp;gt;%s&amp;lt;'

def get_circulation(feed_uri):
    dom = minidom.parse(urllib.urlopen(API_URL % feed_uri))
    entry = dom.getElementsByTagName('entry')[0]
    count = entry.getAttribute('circulation')
    if count == '' or count == '0':
     print 'Error getting feed count'
     sys.exit(1)
    return count

def replace_feedburner_count(count):
    '''Replaces feedburner count in FEED_COUNT_FILE'''
    try:
        for line in fileinput.input(FEED_COUNT_FILE, inplace=1):
     # Comma at the end prevents explicitly writing a newline
            print re.sub(HTML_REGEX, REPLACE_STRING % count, line, 1),
    except OSError, ose:
     print 'File &amp;quot;%s&amp;quot; not found' % FEED_COUNT_FILE

if __name__ == '__main__':
    # First arg is URI
    feed_count = get_circulation(sys.argv[1])
    print feed_count
    if FEED_COUNT_FILE:
        replace_feedburner_count(feed_count)
</pre>
<p>Something like this would be especially cool if you could set thresholds or use <a href="http://docs.python.org/library/optparse.html" title="Python optparse">optparse</a> for advanced options. Useful? Hope so!</p>


<p>Related posts:<ol><li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Python first impressions'>Python first impressions</a></li>
<li><a href='http://eriwen.com/python/site-monitor/' rel='bookmark' title='Site monitoring with Python and cron'>Site monitoring with Python and cron</a></li>
<li><a href='http://eriwen.com/javascript/stacktrace-update/' rel='bookmark' title='Javascript Stacktrace update'>Javascript Stacktrace update</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/python/update-feedburner-count/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Site monitoring with Python and cron</title>
		<link>http://eriwen.com/python/site-monitor/</link>
		<comments>http://eriwen.com/python/site-monitor/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 11:00:23 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=914</guid>
		<description><![CDATA[I recently switched to hosting all of my own websites. While it is liberating to have much more control over my web host, it begs for more maintenance time and better tools to help you monitor your server. 

<image src="http://eriwen.com/images/python_egg_sm.jpg" class="img-left" alt="Baby Python"/>While browsing my <a href="http://github.com/emwendelin">GitHub account</a> I came across <a href="http://www.marksanborn.net">Mark Sanborn</a>'s <a href="http://gist.github.com/177420">site monitoring script</a> and thought: "Hey this is a good idea, let's see what I can make of it". I have been meaning to post more Python here so I updated his code a bit and thought I'd share it with you. I hope you have ideas for improvements.

<h2>Checking site availability with Python</h2>
I didn't feel that this script was big enough to go full <abbr title="Object Oriented">OO</abbr> with it, but if you want to add to it, fork the <a href="http://gist.github.com/187610">gist on GitHub</a> and provide a link in the comments. <strong>You know what'd really be cool is if someone used timeit to get the response time and set thresholds for when the site is too slow.</strong>
 <a href="http://eriwen.com/python/site-monitor/">Continue reading <span class="meta-nav">&#8594;</span></a>


Related posts:<ol><li><a href='http://eriwen.com/python/update-feedburner-count/' rel='bookmark' title='Using Python to update your FeedBurner stats'>Using Python to update your FeedBurner stats</a></li>
<li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Python first impressions'>Python first impressions</a></li>
<li><a href='http://eriwen.com/groovy/groovy-shell-scripts/' rel='bookmark' title='Get groovy for better shell scripts'>Get groovy for better shell scripts</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I recently switched to hosting all of my own websites. While it is liberating to have much more control over my web host, it begs for more maintenance time and better tools to help you monitor your server. </p>
<p><image src="http://eriwen.com/images/python_egg_sm.jpg" class="img-left" alt="Baby Python"/>While browsing my <a href="http://github.com/emwendelin">GitHub account</a> I came across <a href="http://www.marksanborn.net">Mark Sanborn</a>&#8216;s <a href="http://gist.github.com/177420">site monitoring script</a> and thought: &#8220;Hey this is a good idea, let&#8217;s see what I can make of it&#8221;. I have been meaning to post more Python here so I updated his code a bit and thought I&#8217;d share it with you. I hope you have ideas for improvements.</p>
<p class="update">UPDATE: It looks like Mark has made this a full <a href="http://github.com/sanbornm/Site-Monitor">project on GitHub</a> and added timing the requests and command-line options! This is a perfect example of how <acronym title="Open-Source Software">OSS</acronym> projects are started. Check out his <a href="http://www.nixtutor.com/linux/your-chance-to-contribute-to-an-open-source-project/">introductory post</a>.</p>
<h2>Checking site availability with Python</h2>
<p>I didn&#8217;t feel that this script was big enough to go full <abbr title="Object Oriented">OO</abbr> with it, but if you want to add to it, fork the <a href="http://gist.github.com/187610">gist on GitHub</a> and provide a link in the comments. <strong>You know what&#8217;d really be cool is if someone used timeit to get the response time and set thresholds for when the site is too slow.</strong></p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/env python

# sample usage: checksites.py yoursite.com othersite.org

import pickle, os, sys, logging
from httplib import HTTPConnection, socket
from smtplib import SMTP

def email_alert(message, status):
    fromaddr = 'you@gmail.com'
    toaddrs = 'yourphone@txt.att.net'

    server = SMTP('smtp.gmail.com:587')
    server.starttls()
    server.login('you', 'password')
    server.sendmail(fromaddr, toaddrs, 'Subject: %s\r\n%s' % (status, message))
    server.quit()

def get_site_status(url):
    response = get_response(url)
    try:
        if getattr(response, 'status') == 200:
            return 'up'
    except AttributeError:
    	pass
    return 'down'

def get_response(url):
    '''Return response object from URL'''
    try:
        conn = HTTPConnection(url)
        conn.request('HEAD', '/')
        return conn.getresponse()
    except socket.error:
    	return None
    except:
        logging.error('Bad URL:', url)
        exit(1)

def get_headers(url):
    '''Gets all headers from URL request and returns'''
    response = get_response(url)
    try:
        return getattr(response, 'getheaders')()
    except AttributeError:
    	return 'Headers unavailable'

def compare_site_status(prev_results):
    '''Report changed status based on previous results'''

    def is_status_changed(url):
    	status = get_site_status(url)
    	friendly_status = '%s is %s' % (url, status)
    	print friendly_status
    	if url in prev_results and prev_results[url] != status:
            logging.warning(status)
            # Email status messages
            email_alert(str(get_headers(url)), friendly_status)
        prev_results[url] = status

    return is_status_changed

def is_internet_reachable():
    '''Checks Google then Yahoo just in case one is down'''
    if get_site_status('www.google.com') == 'down' and get_site_status('www.yahoo.com') == 'down':
        return False
    return True

def load_old_results(file_path):
    '''Attempts to load most recent results'''
    pickledata = {}
    if os.path.isfile(file_path):
        picklefile = open(file_path, 'rb')
        pickledata = pickle.load(picklefile)
        picklefile.close()
    return pickledata

def store_results(file_path, data):
    '''Pickles results to compare on next run'''
    output = open(file_path, 'wb')
    pickle.dump(data, output)
    output.close()

def main(urls):
    # Setup logging to store time
    logging.basicConfig(level=logging.WARNING, filename='checksites.log',
            format='%(asctime)s %(levelname)s: %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S')

    # Load previous data
    pickle_file = 'data.pkl'
    pickledata = load_old_results(pickle_file)

    # Check sites only if Internet is_available
    if is_internet_reachable():
    	status_checker = compare_site_status(pickledata)
    	map(status_checker, urls)
    else:
        logging.error('Either the world ended or we are not connected to the net.')

    # Store results in pickle file
    store_results(pickle_file, pickledata)

if __name__ == '__main__':
    # First arg is script name, skip it
    main(sys.argv[1:])
</pre>
<p>Basically, this script just checks if the internet is available, then checks each site. If the previous result is available and is different, it sends an email with the headers received so you might get a good idea what&#8217;s going on. Even cooler, you can use the <a href="http://www.emailtextmessages.com/">email specific to your cell phone carrier</a> to get text messages when your sites&#8217; availability changes.</p>
<p><strong>NOTE: You must have some sort of mailer daemon installed</strong>. See <a href="http://www.nixtutor.com/linux/send-mail-with-gmail-and-ssmtp/">How to setup Gmail with sSMTP</a>. You can try it out by editing the appropriate parts of the script and then doing:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
chmod +x checksites.py
./checksites.py eriwen.com yoursite.com
</pre>
<h2>Scheduling it up with cron</h2>
<p>I&#8217;ve already showed you the <a href="http://eriwen.com/productivity/crontab-for-automation/">ins and outs of basic cron scheduling</a>. We can have this run every 5 minutes by typing <code>crontab -e</code> and then adding:</p>
<pre class="brush: bash; light: true; title: ; wrap-lines: false; notranslate">
*/5 * * * * ./path/to/checksites.py yourwebsite.com othersite.org
</pre>
<p>What do you think? Tell me how you&#8217;d make it more &#8220;pythonic&#8221; or otherwise improve it in the comments.</p>


<p>Related posts:<ol><li><a href='http://eriwen.com/python/update-feedburner-count/' rel='bookmark' title='Using Python to update your FeedBurner stats'>Using Python to update your FeedBurner stats</a></li>
<li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Python first impressions'>Python first impressions</a></li>
<li><a href='http://eriwen.com/groovy/groovy-shell-scripts/' rel='bookmark' title='Get groovy for better shell scripts'>Get groovy for better shell scripts</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/python/site-monitor/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Python first impressions</title>
		<link>http://eriwen.com/python/first-impressions/</link>
		<comments>http://eriwen.com/python/first-impressions/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 11:00:52 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=621</guid>
		<description><![CDATA[A few days ago I got my first <a href="" title="The Python Language">Python</a> project. I'd like to share references I've found, and what I like or dislike about the language. I hope to give insight to would-be Python dabblers and ideas to current Pythoneers.

<h2>Good resources I've found</h2>
I have found some good resources online for Python and <a href="http://www.jython.org/" title="The Jython language">Jython</a>, but I know I didn't find them all so if you Python-istas could put some in the comments I'd be very grateful :)
<ul style="margin-left: 3em; list-style-type: upper-roman;"><li>The somewhat famous <a href="http://dirtsimple.org/2004/12/python-is-not-java.html">Python is not Java</a> article</li>
<li><a href="http://www.python.org/doc/" title="Python APIs">Python Documentation Index</a></li>
<li><a href="http://docs.python.org/">Python 2.6.1 Docs</a></li>
<li><a href="http://www.angelfire.com/tx4/cus/notes/python.html">Python Language Notes</a> by <a href="http://www.angelfire.com/tx4/cus/index.html">Chris Rathman</a></li>
<li><a href="http://www.jython.org/Project/">The Jython Project</a></li></ul>
 <a href="http://eriwen.com/python/first-impressions/">Continue reading <span class="meta-nav">&#8594;</span></a>


Related posts:<ol><li><a href='http://eriwen.com/python/update-feedburner-count/' rel='bookmark' title='Using Python to update your FeedBurner stats'>Using Python to update your FeedBurner stats</a></li>
<li><a href='http://eriwen.com/python/site-monitor/' rel='bookmark' title='Site monitoring with Python and cron'>Site monitoring with Python and cron</a></li>
<li><a href='http://eriwen.com/python/griffon-jython-plugin/' rel='bookmark' title='Griffon, meet Jython'>Griffon, meet Jython</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://eriwen.com/images/python.png" alt="Python logo" class="img-left"/>A few days ago I got my first <a href="" title="The Python Language">Python</a> project. I&#8217;d like to share references I&#8217;ve found, and what I like or dislike about the language. I hope to give insight to would-be Python dabblers and ideas to current Pythoneers.</p>
<h2>Good resources I&#8217;ve found</h2>
<p>I have found some good resources online for Python and <a href="http://www.jython.org/" title="The Jython language">Jython</a>, but I know I didn&#8217;t find them all so if you Python-istas could put some in the comments I&#8217;d be very grateful :)</p>
<ol>
<li>The somewhat famous <a href="http://dirtsimple.org/2004/12/python-is-not-java.html">Python is not Java</a> article</li>
<li><a href="http://www.python.org/doc/" title="Python APIs">Python Documentation Index</a></li>
<li><a href="http://docs.python.org/">Python 2.6.1 Docs</a></li>
<li><a href="http://www.angelfire.com/tx4/cus/notes/python.html">Python Language Notes</a> by <a href="http://www.angelfire.com/tx4/cus/index.html">Chris Rathman</a></li>
<li><a href="http://www.jython.org/Project/">The Jython Project</a></li>
</ol>
<h2>What I like so far</h2>
<p>I like that a lot of common operations are very easy. Take for example:</p>
<pre class="brush: python; title: ; notranslate">
# 3 Hellos in Python
hellos = 'Hello ' * 3
</pre>
<p>as opposed to </p>
<pre class="brush: java; title: ; notranslate">
// 3 Hellos in Java
String hellos = &quot;&quot;;
for (int i = 0; i &lt; 3; i++) {
    hellos += &quot;Hello &quot;;
}
</pre>
<p>There are a bunch of other features that come to mind, like <em>string formatting</em>, <em>list manipulation</em>, and <em>variable and default-valued arguments</em>. Oh, and of course <em>closures</em> are very straightforward (many thanks to <a href="http://www.hvergi.net/">Arnar</a> for a <em>real</em> closure example):</p>
<pre class="brush: python; title: ; notranslate">
def outer(your_name):
    title = random.choice([&quot;Mr&quot;, &quot;Mrs&quot;, &quot;Miss&quot;])

    def greeter(greeting):
        print greeting, title, your_name

    return greeter

g = outer(&quot;Eric&quot;)  # invoke it

# g now contains a reference to the inner
# function, but as it references variables
# from the local scope of outer, the invocation
# data has been stored in a closure
# Execution of outer is finished, but g can
# still reference its local variables through
# the closure:

g(&quot;Hi&quot;)  # prints &quot;Hi Miss Eric&quot; :D
</pre>
<p>I could go on and on, but you really ought to read the <a href="http://docs.python.org/">documentation</a> to see all of its features. Actually there&#8217;s not all that much to it!</p>
<h2>Troubles I have with it</h2>
<p>I wish I could find more documentation with simple code examples. I&#8217;m sure there are a bunch of blog posts out there but it&#8217;d be nice if there were more included with the documentation.</p>
<p>Passing arguments by reference doesn&#8217;t seem to be possible, which is fine, but different. I&#8217;m not totally used to the lack of curly braces, but I like the fact that you <em>must</em> have good formatting to have runnable Python. I was surprised to learn that Python is <em>strongly typed</em> which in some way I think is odd because it seems like it&#8217;d be simpler if it was weakly typed. </p>
<pre class="brush: python; title: ; notranslate">
a = &quot;17&quot;
b = 25
print a + b  # Nope!
</pre>
<p>One last thing is classes. I&#8217;m not sure I have my head around how they really work in Python. I&#8217;m sure I&#8217;ll get the hang of it soon.</p>
<h2>Conclusion</h2>
<p>Overall I&#8217;m thoroughly impressed with the language. There almost seems to be a Zen-like aura around Python code that is written with the simplicity the language creators intended.</p>
<p>Obviously I still have a lot to learn, so please help me out if you have some advice in the comments!</p>


<p>Related posts:<ol><li><a href='http://eriwen.com/python/update-feedburner-count/' rel='bookmark' title='Using Python to update your FeedBurner stats'>Using Python to update your FeedBurner stats</a></li>
<li><a href='http://eriwen.com/python/site-monitor/' rel='bookmark' title='Site monitoring with Python and cron'>Site monitoring with Python and cron</a></li>
<li><a href='http://eriwen.com/python/griffon-jython-plugin/' rel='bookmark' title='Griffon, meet Jython'>Griffon, meet Jython</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/python/first-impressions/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
	</channel>
</rss>

