<?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>Limina.Log &#187; Python</title>
	<atom:link href="http://log.liminastudio.com/tag/python/feed" rel="self" type="application/rss+xml" />
	<link>http://log.liminastudio.com</link>
	<description>Research &#38; Development at Limina.Studio</description>
	<lastBuildDate>Sun, 15 Jan 2012 21:25:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Controlling Deluge Auto-Management and File Priorities via Python</title>
		<link>http://log.liminastudio.com/programming/controlling-deluge-auto-management-and-file-priorities-via-python</link>
		<comments>http://log.liminastudio.com/programming/controlling-deluge-auto-management-and-file-priorities-via-python#comments</comments>
		<pubDate>Tue, 15 Nov 2011 21:27:58 +0000</pubDate>
		<dc:creator>Tedb0t</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[BitTorrent]]></category>
		<category><![CDATA[Deluge]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://log.liminastudio.com/?p=943</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/controlling-deluge-auto-management-and-file-priorities-via-python' addthis:title='Controlling Deluge Auto-Management and File Priorities via Python '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div>Today I was working away from my home file server which runs the BitTorrent server Deluge.  My Deluge Web UI stopped working for some reason (and it never worked that well in the first place) and I really needed to start a torrent at home.  Deluge has an &#8220;Auto Managed&#8221; feature that&#8217;s enabled by default, [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/controlling-deluge-auto-management-and-file-priorities-via-python' addthis:title='Controlling Deluge Auto-Management and File Priorities via Python '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div><p>Today I was working away from my home file server which runs the BitTorrent server Deluge.  My Deluge Web UI stopped working for some reason (and it never worked that well in the first place) and I really needed to start a torrent at home.  Deluge has an &#8220;Auto Managed&#8221; feature that&#8217;s enabled by default, but since I seed a lot of torrents, it actually prevents a new torrent from starting to download automatically, so I have to disable that and the resume the torrent after adding it.  Thankfully Deluge has a Python client interface we can use to write our own scripts.</p>
<p>Here&#8217;s an example script that adds a URL from an argument with auto_managed turned off:</p>
<pre>#!/usr/bin/env python
# encoding: utf-8
"""
DelugeEasyAdd

Starts a new Deluge torrent from a URL.

Created by Ted Hayes.

"""

import urllib, os, sys, re
# Import the client module
from deluge.ui.client import client
# Import the reactor module from Twisted - this is for our mainloop
from twisted.internet import reactor

# Set up the logger to print out errors
from deluge.log import setupLogger
setupLogger()

# Connect to a daemon running on the localhost
# We get a Deferred object from this method and we use this to know if and when
# the connection succeeded or failed.
d = client.connect()

PRIO_NORMAL = 1
PRIO_MAX = 5

torrentURL = sys.argv[1]
# btjunkie URLs use 'download.torrent' as the filename, get a better one
if re.search("btjunkie", torrentURL):
    filename = re.findall("torrent\/(.*?)\/", torrentURL)[0]
else:
    filename = os.path.basename(torrentURL)

print "Using filename: %s" % filename

def addTorrent():
    client.core.add_torrent_url(torrentURL, '/home/daleth/Downloads/'+filename, {'auto_managed':False}).addCallback(added)

def added(s):
    print "Added status: ",s
    #client.core.resume_torrent()
    disconnect()

# We create a callback function to be called upon a successful connection
def on_connect_success(result):
    print "Connection was successful!"
    addTorrent()

def disconnect():
    print "disconnecting"
    client.disconnect()
    reactor.stop()

# We add the callback to the Deferred object we got from connect()
d.addCallback(on_connect_success)

# We create another callback function to be called when an error is encountered
def on_connect_fail(result):
    print "Connection failed!"
    print "result:", result

# We add the callback (in this case it's an errback, for error)
d.addErrback(on_connect_fail)

# Run the twisted main loop to make everything go
reactor.run()</pre>
<p>I still have to figure out how to then automatically resume the torrent.</p>
<p>Here are some helpful links:</p>
<p><a href="http://dev.deluge-torrent.org/wiki/Development/UiClient">UIClient Documentation<br />
</a></p>
<p><a href="http://dev.deluge-torrent.org/wiki/Development/1.3/UIClient">UIClient Example </a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://log.liminastudio.com/programming/controlling-deluge-auto-management-and-file-priorities-via-python/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SoundcloudScraper: Download all of an artist&#8217;s Soundcloud tracks automatically</title>
		<link>http://log.liminastudio.com/programming/soundcloudscraper-download-all-of-an-artists-soundcloud-tracks-automatically</link>
		<comments>http://log.liminastudio.com/programming/soundcloudscraper-download-all-of-an-artists-soundcloud-tracks-automatically#comments</comments>
		<pubDate>Wed, 20 Jul 2011 01:59:03 +0000</pubDate>
		<dc:creator>Tedb0t</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Music]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[scraper]]></category>
		<category><![CDATA[soundcloud]]></category>

		<guid isPermaLink="false">http://log.liminastudio.com/?p=885</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/soundcloudscraper-download-all-of-an-artists-soundcloud-tracks-automatically' addthis:title='SoundcloudScraper: Download all of an artist&#8217;s Soundcloud tracks automatically '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div>Today I was listening to a great Soundcloud artist with 22 tracks, all available to freely download.  Since I didn&#8217;t see an option to download them all en masse, I wrote up a nifty script to do it, then added a bunch of features to make it shiny. Download the SoundcloudScraper zip file here:  soundcloudScraper_v1  [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/soundcloudscraper-download-all-of-an-artists-soundcloud-tracks-automatically' addthis:title='SoundcloudScraper: Download all of an artist&#8217;s Soundcloud tracks automatically '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div><p>Today I was listening to a great <a href="http://www.soundcloud.com">Soundcloud</a> artist with 22 tracks, all available to freely download.  Since I didn&#8217;t see an option to download them all <em>en masse,</em> I wrote up a nifty script to do it, then added a bunch of features to make it shiny.</p>
<p>Download the SoundcloudScraper zip file here:  <a href="http://log.liminastudio.com/wp-content/uploads/2011/07/soundcloudScraper_v1.zip">soundcloudScraper_v1</a>  To use, you&#8217;ll need Python; I looked into making it a standalone binary but I&#8217;m afraid that&#8217;ll have to wait for another time.  Open up a terminal and go to the directory the script is in, and type:</p>
<p><code>./soundcloudScraper.py artistname</code></p>
<p>This will automatically download all the available tracks by that artist, meaning tracks with a &#8216;Download&#8217; button.  You can also specify multiple artists:</p>
<p><code>./soundcloudScraper.py artist1 artist2 artist3</code></p>
<p>This script uses the fantastic <a href="http://nadiana.com/animated-terminal-progress-bar-in-python">Animated Terminal Progress Bar module</a> by Nadia Alramli!  If you find any bugs or get some use out of the script, leave a comment! Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://log.liminastudio.com/programming/soundcloudscraper-download-all-of-an-artists-soundcloud-tracks-automatically/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Dealing with Python 2.x UnicodeDecodeErrors</title>
		<link>http://log.liminastudio.com/programming/dealing-with-python-2-x-unicodedecodeerrors</link>
		<comments>http://log.liminastudio.com/programming/dealing-with-python-2-x-unicodedecodeerrors#comments</comments>
		<pubDate>Tue, 04 Jan 2011 20:32:22 +0000</pubDate>
		<dc:creator>Tedb0t</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://log.liminastudio.com/?p=754</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/dealing-with-python-2-x-unicodedecodeerrors' addthis:title='Dealing with Python 2.x UnicodeDecodeErrors '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div>Tired of seeing this? &#60;type 'exceptions.UnicodeDecodeError'&#62; at /such/and/such 'ascii' codec can't decode byte 0xf8 in position 12: ordinal not in range(128) So am I.  I had a bytestring with extended characters in it: data = '\xfcnic\xf8de test' And no matter what I tried: data.decode('utf-8') &#8230;I kept getting errors. Turns out those extended characters simply aren&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/dealing-with-python-2-x-unicodedecodeerrors' addthis:title='Dealing with Python 2.x UnicodeDecodeErrors '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div><p>Tired of seeing this?</p>
<pre>&lt;type 'exceptions.UnicodeDecodeError'&gt; at /such/and/such
'ascii' codec can't decode byte 0xf8 in position 12: ordinal not in range(128)</pre>
<p>So am I.  I had a bytestring with extended characters in it:</p>
<pre>data = '\xfcnic\xf8de test'</pre>
<p>And no matter what I tried:</p>
<pre>data.decode('utf-8')</pre>
<p>&#8230;I kept getting errors.  Turns out those extended characters simply aren&#8217;t in the utf-8 codec, so I tried latin-1:</p>
<pre>data.decode('latin-1')</pre>
<p>And it works!  At long last!!</p>
]]></content:encoded>
			<wfw:commentRss>http://log.liminastudio.com/programming/dealing-with-python-2-x-unicodedecodeerrors/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HowTo: Use OpenID with Web.py</title>
		<link>http://log.liminastudio.com/programming/howto-use-openid-with-web-py</link>
		<comments>http://log.liminastudio.com/programming/howto-use-openid-with-web-py#comments</comments>
		<pubDate>Tue, 07 Dec 2010 23:32:02 +0000</pubDate>
		<dc:creator>Tedb0t</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[OpenID]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[web.py]]></category>

		<guid isPermaLink="false">http://log.liminastudio.com/?p=742</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/howto-use-openid-with-web-py' addthis:title='HowTo: Use OpenID with Web.py '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div>I&#8217;m going to be using OpenID as a universal login for a new webapp I&#8217;m working on. As luck would have it Web.py has a module just for this, and the API is super simple!  Now that I&#8217;ve got this working I&#8217;ve got to figure out how to actually integrate it into the app; this link [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/howto-use-openid-with-web-py' addthis:title='HowTo: Use OpenID with Web.py '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div><p>I&#8217;m going to be using <a href="http://openid.net/add-openid/">OpenID as a universal login</a> for a new webapp I&#8217;m working on.  As luck would have it Web.py has a module just for this, and the API is super simple!  Now that I&#8217;ve got this working I&#8217;ve got to figure out how to actually integrate it into the app; <a href="http://www.plaxo.com/api/openid_recipe">this link</a> looks helpful towards that.</p>
<ol>
<li><a href="http://webpy.org/install">Install web.py</a>:
<pre>sudo easy_install web.py</pre>
<p>or</p>
<pre>sudo apt-get install python-webpy</pre>
</li>
<li>
<pre>sudo easy_install python-openid</pre>
<p>or</p>
<pre>sudo apt-get install python-openid</pre>
</li>
<li>main.py:
<pre>import web, web.webopenid

urls = (
    r'/openid', 'web.webopenid.host',
    r'/', 'Index'
)

app = web.application(urls, globals())

class Index:
    def GET(self):
        body = '''
        &lt;html&gt;&lt;head&gt;&lt;title&gt;Web.py OpenID Test&lt;/title&gt;&lt;/head&gt;
        &lt;body&gt;
            %s
        &lt;/body&gt;
        &lt;/html&gt;
        ''' % (web.webopenid.form('/openid'))

        return body

if __name__ == "__main__": app.run()</pre>
</li>
<li>Run
<pre>python main.py</pre>
</li>
<li>Go to http://localhost:8080</li>
<li>Voilà!</li>
</ol>
<p>I&#8217;ve also added this to the <a href="http://webpy.org/cookbook/openid">Web.py cookbook</a>.  Please let me know if you find any bugs or mistakes!</p>
]]></content:encoded>
			<wfw:commentRss>http://log.liminastudio.com/programming/howto-use-openid-with-web-py/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Managing Python daemon processes with Bash</title>
		<link>http://log.liminastudio.com/programming/killing-a-list-of-processes-easily-with-bash</link>
		<comments>http://log.liminastudio.com/programming/killing-a-list-of-processes-easily-with-bash#comments</comments>
		<pubDate>Sat, 30 Oct 2010 00:11:30 +0000</pubDate>
		<dc:creator>Tedb0t</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://log.liminastudio.com/?p=732</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/killing-a-list-of-processes-easily-with-bash' addthis:title='Managing Python daemon processes with Bash '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div>Usually if you want to kill some processes they have to have unique names or you have to know their process IDs.  Lately I&#8217;ve had a group of python daemon scripts that need to be restarted occasionally, so instead of looking at a list, finding the pids and killing them manually, here&#8217;s an  approach that [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/killing-a-list-of-processes-easily-with-bash' addthis:title='Managing Python daemon processes with Bash '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div><p>Usually if you want to kill some processes they have to have unique names or you have to know their process IDs.  Lately I&#8217;ve had a group of python daemon scripts that need to be restarted occasionally, so instead of looking at a list, finding the pids and killing them manually, here&#8217;s an  approach that uses PID files to keep note of the process&#8217; ID, so you can just reference the file.  There&#8217;s a Bash script and a snippet that should be at the beginning of the python scripts.  Right now this is in conjunction with <a href="http://mmonit.com/monit/">monit</a>, which will start the scripts if they&#8217;re not running.  Monit can restart them for you, too, but apparently I was feeling masochistic this day.  This is adapted from original code by <a href="http://knifeandfork.org/">Brian House</a> (thanks Brian!)</p>
<p>restart.sh:</p>
<pre>#!/bin/bash

PROCESS_PATH="run/"
PROCESS_LIST=( "render_city.pid" "render_cards.pid" "email_sender.pid" "sms_sender.pid" )

function killProcess {
    echo "killProcess $1"
    PIDFILE=$PROCESS_PATH$1
    PID=0
    if [ -e $PIDFILE ]; then
        PID=`cat $PIDFILE`
        if [ "x" == "x$PID" ]; then
            PID=0
        fi
    fi
    if [ "$PID" != "0" ]; then
        echo "--&gt; Killing current process $PID..."
        sudo kill $PID
    else
        echo '--&gt; Nothing to kill.'
    fi
}

if [ ! -z "$1" ]; then
    if [ $1 == "all" ]; then
        echo "*** Killing all"
        chmod +x daemons/*  # since svn strips permissions, always make sure they're executable

        ELEMENTS=${#PROCESS_LIST[@]}
        for (( i=0; i&lt;$ELEMENTS; i++)); do
            killProcess ${PROCESS_LIST[${i}]}
        done
    fi
fi</pre>
<p>Here&#8217;s a python function that manages the PID file (written by Brian, goes in a util.py module):</p>
<pre>def confirm_pid(run_folder):
    import sys, os, signal, __main__
    name = prefix('.', os.path.basename(__main__.__file__))
    log.info("Attempting to launch daemon %s..." % name)
    pid = str(os.getpid())
    pidfile = "%s%s.pid" % (run_folder, name)
    if os.path.isfile(pidfile):
        old_pid = open(pidfile).read()
        log.warning("--&gt; pidfile already exists for %s, attempting to kill process..." % old_pid)
        try:
            result = os.kill(int(old_pid), signal.SIGKILL)
        except OSError, e:
            if e.args[0] == 3:
                log.warning("--&gt; no process with pid %s" % old_pid)
            else:
                log.error(e)
                exit()
        else:
            log.info("--&gt; killed process %s" % old_pid)
        try:
            os.unlink(pidfile)
        except OSError, e:
            log.error("--&gt; could not remove pidfile, %s" % pidfile)
            exit()
    open(pidfile, 'w').write(pid)
    log.info("--&gt; launched with pid %s" % pid)</pre>
<p>&#8230;and the snippet that goes at the top of the daemon:</p>
<pre>import sys, os
sys.path.append(os.path.dirname(__file__) + "/../")
util.confirm_pid(os.path.dirname(__file__) + "/../run/")</pre>
]]></content:encoded>
			<wfw:commentRss>http://log.liminastudio.com/programming/killing-a-list-of-processes-easily-with-bash/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to do time benchmarks in Python</title>
		<link>http://log.liminastudio.com/programming/how-to-do-time-benchmarks-in-python</link>
		<comments>http://log.liminastudio.com/programming/how-to-do-time-benchmarks-in-python#comments</comments>
		<pubDate>Thu, 14 Oct 2010 23:30:59 +0000</pubDate>
		<dc:creator>Tedb0t</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Benchmarking]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://log.liminastudio.com/?p=726</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/how-to-do-time-benchmarks-in-python' addthis:title='How to do time benchmarks in Python '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div>Say you&#8217;ve got a time-intensive script and you want to benchmark how long it takes—here&#8217;s a really simple and effective snippet. from time import * #not best practice but... meh startTime = time() # super-complicated, time-consuming code elapsed = time() - startTime print "Finished. Total time: " + strftime('%H:%M:%S', gmtime(elapsed)) Simple!]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/how-to-do-time-benchmarks-in-python' addthis:title='How to do time benchmarks in Python '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div><p>Say you&#8217;ve got a time-intensive script and you want to benchmark how long it takes—here&#8217;s a really simple and effective snippet.</p>
<pre>from time import * #not best practice but... meh
startTime = time()

# super-complicated, time-consuming code

elapsed = time() - startTime
print "Finished. Total time: " + strftime('%H:%M:%S', gmtime(elapsed))</pre>
<p>Simple!</p>
]]></content:encoded>
			<wfw:commentRss>http://log.liminastudio.com/programming/how-to-do-time-benchmarks-in-python/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>POSTing a ByteArray from Flash to Web.py</title>
		<link>http://log.liminastudio.com/programming/posting-a-bytearray-from-flash-to-web-py</link>
		<comments>http://log.liminastudio.com/programming/posting-a-bytearray-from-flash-to-web-py#comments</comments>
		<pubDate>Mon, 16 Aug 2010 21:26:55 +0000</pubDate>
		<dc:creator>Tedb0t</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[AS3]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[web.py]]></category>

		<guid isPermaLink="false">http://log.liminastudio.com/?p=693</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/posting-a-bytearray-from-flash-to-web-py' addthis:title='POSTing a ByteArray from Flash to Web.py '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div>&#8230;turns out to be really straightforward using the web.data() method (thanks to Brian for the heads-up!): Flash code—for this example you&#8217;ll need the AS3CoreLib JPGEncoder class: _video = new Video(640, 480); _camera = Camera.getCamera(); _camera.setMode(640, 480, 30); _video.attachCamera(_camera); addChild(_video); _jpegEncoder = new JPGEncoder(60); _urlReq = new URLRequest(); _urlReq.url = "http://localhost:8080/addImage"; _urlReq.method = URLRequestMethod.POST; _urlLoader = [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/posting-a-bytearray-from-flash-to-web-py' addthis:title='POSTing a ByteArray from Flash to Web.py '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div><p>&#8230;turns out to be really straightforward using the web.data() method (thanks to <a href="http://brianhouse.net/">Brian</a> for the heads-up!):</p>
<p>Flash code—for this example you&#8217;ll need the <a href="http://github.com/mikechambers/as3corelib">AS3CoreLib</a> JPGEncoder class:</p>
<pre>_video = new Video(640, 480);
_camera = Camera.getCamera();
_camera.setMode(640, 480, 30);
_video.attachCamera(_camera);
addChild(_video);

_jpegEncoder = new JPGEncoder(60);

_urlReq = new URLRequest();
_urlReq.url = "http://localhost:8080/addImage";
_urlReq.method = URLRequestMethod.POST;

_urlLoader = new URLLoader();

_snapShot = new BitmapData(_camera.width, _camera.height);
_snapShot.draw(_video);
_snapShotImage = new Bitmap(_snapShot);
var jpgStream:ByteArray = _jpegEncoder.encode(_snapShot);
_urlReq.data = jpgStream;

try {
	_urlLoader.load(_urlReq);
} catch (e:Error) {
	trace("Remote.request caught error: "+e);
}</pre>
<p>And the Python (using web.py):</p>
<pre>import web

urls = (
  '/addImage', 'addImage'
)

app = web.application(urls, globals())

class addImage:
    def POST(self):
        data = web.data()
        f = open("test.jpg", 'wb')
        f.write(data)

if __name__ == "__main__": app.run()</pre>
<p>That&#8217;s it!</p>
]]></content:encoded>
			<wfw:commentRss>http://log.liminastudio.com/programming/posting-a-bytearray-from-flash-to-web-py/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running Python on your OSX Apache server: mod_python</title>
		<link>http://log.liminastudio.com/programming/running-python-on-your-apache-server-mod_python</link>
		<comments>http://log.liminastudio.com/programming/running-python-on-your-apache-server-mod_python#comments</comments>
		<pubDate>Mon, 09 Aug 2010 02:51:05 +0000</pubDate>
		<dc:creator>Tedb0t</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Writing]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://log.liminastudio.com/?p=674</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/running-python-on-your-apache-server-mod_python' addthis:title='Running Python on your OSX Apache server: mod_python '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div>Want to interpret Python scripts in Apache on your OSX installation?  Look no further! After about 4 hours of repeated head-to-wall collisions, I finally managed to get mod_python running with Apache 2.2.14 on my Snow Leopard machine.  Here&#8217;s what I had to do: Use the MacPorts Apache instead of MAMP.  I absolutely could not get [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/programming/running-python-on-your-apache-server-mod_python' addthis:title='Running Python on your OSX Apache server: mod_python '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div><p>Want to interpret Python scripts in Apache on your OSX installation?  Look no further!</p>
<p>After about 4 hours of repeated head-to-wall collisions, I finally managed to get mod_python running with Apache 2.2.14 on my Snow Leopard machine.  Here&#8217;s what I had to do:</p>
<ol>
<li>Use the <a href="http://www.macports.org/">MacPorts</a> Apache instead of MAMP.  I absolutely could not get this to work for MAMP, which might be because MAMP uses version 2.062 of Apache.  All the following instructions are for MacPorts installs.  Once you install MacPorts, you can install Apache by doing
<pre>sudo port install apache</pre>
</li>
<li>Now you need mod_python, which is a module for Apache that allows the HTTP server to use the python interpreter &#8220;inside&#8221; the server.  With MacPorts, just do
<pre>sudo port install mod_python</pre>
<p>If for some reason this doesn&#8217;t work, I&#8217;ve <a href="http://log.liminastudio.com/wp-content/uploads/2010/08/mod_python-help.zip">packaged</a> it up along with the mod_python python package described next.  Put it in</p>
<pre>/opt/local/apache2/modules</pre>
</li>
<li>Make sure you have the mod_python Python package (yeah, it&#8217;s got the exact same name as the Apache module but is a completely different thing).  Get into your Python interpreter and try
<pre>import mod_python</pre>
<p>If it works, rejoice.  If not, I&#8217;ve <a href="http://log.liminastudio.com/wp-content/uploads/2010/08/mod_python-help.zip">included mine in a zip</a> because I could not for the life of me figure out where to get it from, but I had it in one of my other Python installs. It goes here:</p>
<pre>/Library/Python/2.6/site-packages</pre>
</li>
<li>Edit your httpd.conf file by adding the following:
<pre>LoadModule python_module modules/mod_python.so

SetHandler mod_python
PythonHandler mod_python.publisher
PythonDebug On</pre>
<p>This first tells Apache to load the module, which is a shared object file (.so).  <em>Technical note for the curious:</em> A shared object is a binary that contains compiled functions that can be directly addressed in memory, so you can call functions in it given a header file.  It&#8217;s similar to a Windows .dll.</p>
<p>Anyway, the rest tells Apache to use mod_python&#8217;s VERY handy &#8220;publisher&#8221; function, <a href="http://www.modpython.org/live/current/doc-html/hand-pub.html">described here</a>.  This is a REALLY fast and easy way to start writing Python programs for the web.  Follow the examples there and you should be good to go!  Enjoy!</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://log.liminastudio.com/programming/running-python-on-your-apache-server-mod_python/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Developing the Enpersonator</title>
		<link>http://log.liminastudio.com/itp/developing-the-enpersonator</link>
		<comments>http://log.liminastudio.com/itp/developing-the-enpersonator#comments</comments>
		<pubDate>Tue, 02 Mar 2010 14:31:50 +0000</pubDate>
		<dc:creator>Tedb0t</dc:creator>
				<category><![CDATA[ITP]]></category>
		<category><![CDATA[Learning Bit by Bit]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Generative Text]]></category>
		<category><![CDATA[N-Grams]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Spam]]></category>

		<guid isPermaLink="false">http://log.liminastudio.com/?p=554</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/itp/developing-the-enpersonator' addthis:title='Developing the Enpersonator '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div>Using blog corpora from The Blog Authorship Corpus and the Political Blog Corpora, I have begun developing a simple blog-post generator for Enpersonator, the identity-creating software part of Automenon, an artwork in progress with Sofy Yuditskaya. See Enpersonator in action here: http://soniayuditskaya.tumblr.com/ Enpersonator is in development here: http://github.com/virgildisgr4ce/Enpersonator.  It requires the Python Tumblr library, which [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style " addthis:url='http://log.liminastudio.com/itp/developing-the-enpersonator' addthis:title='Developing the Enpersonator '  ><a class="addthis_button_facebook_like" fb:like:layout="button_count"></a><a class="addthis_button_tweet"></a><a class="addthis_counter addthis_pill_style"></a></div><p>Using blog corpora from <a href="http://u.cs.biu.ac.il/~koppel/BlogCorpus.htm">The Blog Authorship Corpus</a> and the <a href="http://www.ark.cs.cmu.edu/blog-data/">Political Blog Corpora</a>, I have begun developing a simple blog-post generator for Enpersonator, the identity-creating software part of Automenon, an artwork in progress with Sofy Yuditskaya.</p>
<p>See Enpersonator in action here: <a href="http://soniayuditskaya.tumblr.com/">http://soniayuditskaya.tumblr.com/</a></p>
<p>Enpersonator is in development here: <a href="http://github.com/virgildisgr4ce/Enpersonator">http://github.com/virgildisgr4ce/Enpersonator</a>.  It requires the Python <a href="http://code.google.com/p/python-tumblr/">Tumblr library</a>, which requires <a href="http://www.djangoproject.com/download/">Django</a> for its utilities.  The Markov Generator is modified from <a href="decontextualize.com/teaching/dwwp/topics-n-grams-and-markov-chains/">Adam Parrish&#8217;s</a>.</p>
<p>The current version uses all 5 of the blogs in the Political Blog Corpora, comprising 133,953 tokens.  Not too shabby, but still not enough to avoid lots of wholesale reproductions.</p>
]]></content:encoded>
			<wfw:commentRss>http://log.liminastudio.com/itp/developing-the-enpersonator/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

