<?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>Graham King</title>
	<atom:link href="http://www.darkcoding.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.darkcoding.net</link>
	<description>Solvitas perambulum</description>
	<lastBuildDate>Fri, 11 May 2012 16:57:26 +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>Ward Cunningham quotes</title>
		<link>http://www.darkcoding.net/society/ward-cunningham-quotes/</link>
		<comments>http://www.darkcoding.net/society/ward-cunningham-quotes/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 00:14:24 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Society]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[coffeescript]]></category>
		<category><![CDATA[ward cunningham]]></category>
		<category><![CDATA[wiki]]></category>

		<guid isPermaLink="false">http://darkcoding.ge1.ca/?p=1500</guid>
		<description><![CDATA[There&#8217;s an excellent interview of Ward Cunningham at InfoQ (Nov 2011). He talks about agile, wiki&#8217;s (including smallest-federated-wiki), meta-programming, CoffeeScript, but mainly about living as a developer. He is fascinating and motivating. Here are some of my favorite quotes : On pair programming / social coding I don’t think any developer really wanted to work [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s an excellent <a href="http://www.infoq.com/interviews/ward-cunningham-agile-10" target="_blank" class="external">interview of Ward Cunningham at InfoQ (Nov 2011)</a>. He talks about agile, wiki&#8217;s (including <a href="https://github.com/WardCunningham/Smallest-Federated-Wiki" target="_blank" class="external">smallest-federated-wiki</a>), meta-programming, <a href="http://coffeescript.org/" target="_blank" class="external">CoffeeScript</a>,  but mainly about living as a developer. He is fascinating and motivating. Here are some of my favorite quotes :</p>

<p>On pair programming / social coding</p>

<blockquote>
  <p>I don’t think any developer really wanted to work alone, but they got a reputation as being loners that was unjustified because they did so much in their head.</p>
</blockquote>

<p>On agile&#8217;s pace of development</p>

<blockquote>
  <p>I feel that the formulation of most Agile methods are a little plodding, you are coming in, you do the same amount of work every day, but you don’t have days go by where nothing gets done. Like the tortoise and the hair, and the tortoise wins the race, because the tortoise doesn’t get stuck.</p>
</blockquote>

<p><span id="more-1500"></span></p>

<p>On estimation</p>

<blockquote>
  <p>If you say what is the business need and what can we do, and if we know what we don’t know and we make a plan for that the next week, and then just work away and don’t apologise for what’s there, don’t promise things you don’t know you can do, in earnest, chip away at it.</p>
  
  <p>Just know more tomorrow than you know today, and that can be about the code that you have to work with or what the real needs are. And that is the basis of anything Agile, and that can be applied anywhere.</p>
</blockquote>

<p>On technical debt</p>

<blockquote>
  <p>If you want to go fast you take some debt. But the misunderstanding was that people thought that you never have to pay it back. If you are going to take on debt you have to pay it back or you go out of business. It’s called bankruptcy and there have been plenty of bankrupt projects.</p>
</blockquote>

<p>On meta-programming</p>

<blockquote>
  <p>.. in something as complex and as multidimensional as product design, there is a lot of ways to approach it and sometimes if you just step back and say &#8220;This way is just a slug, I wonder if there is a shortcut going around this way&#8221;, and like I say the computer is really powerful, how can you have that computer help you in a way that most people wouldn’t think that they are allowed to program.</p>
</blockquote>

<p>On the link between wiki&#8217;s and agile</p>

<blockquote>
  <p>if you think about [wiki] what it really does is, how can we make a database useful when the database is incomplete? Well that’s exactly the same as how can we make a computer program useful when the computer program is incomplete. Agile is all about first iteration, you make something that works, and then you add more to it, so you grow it. Well wiki is the same thing, how do I make a database of ideas in my company, that’s incomplete but still useful enough that people want to add to it?</p>
</blockquote>

<p>Advice</p>

<blockquote>
  <p>Hang in there. I’ve devoted my life to programming, I think programming is one of the most powerful ways you can exercise your mind. I found that I can do a day job and serve whoever is paying my salary in a way that respects their goals, and still have energy left at the end of the day and do things just to please me. Or to please people who know me.</p>
  
  <p>And I would say that Agile is a pretty marvellous set of values, I say open source is a different but pretty marvellous set of values and both of them are based on understanding code. So I say don’t hesitate to learn more about code, don’t hesitate to do it in an Agile way, do it test driven, maybe work with friends, but don’t hesitate to open it up.</p>
  
  <p>I think that it’s easy to be overwhelmed you say &#8220;Gosh I just learnt this and now it’s that&#8221;, but I tell you, you put two days into studying something and you are already half way to expert. Stuff is coming out that fast, take the time and there is great blog posts on stuff and learn something new every week.</p>
</blockquote>

<p>On CoffeeScript and the browser environment</p>

<blockquote>
  <p>Coffee Script and the environment will all the powerful browsers is the closest I&#8217;ve felt to the power I had twenty years ago in SmallTalk.  But it’s not in one machine for one person, it’s on the whole world for the whole world. And I am excited to go down the stairs because there is a lot more to Coffee Script than I even knew and <strong>I learned it last night and I am going to go apply it and in another week I will be an expert. And you can do it too.</strong></p>
</blockquote>

<p>In summary</p>

<blockquote>
  <p><strong>And we are all programmers, so let’s program.</strong></p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/society/ward-cunningham-quotes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Code coverage in django with &#8216;coverage&#8217; and &#8216;django-jenkins&#8217;</title>
		<link>http://www.darkcoding.net/software/code-coverage-in-django-with-coverage-and-django-jenkins/</link>
		<comments>http://www.darkcoding.net/software/code-coverage-in-django-with-coverage-and-django-jenkins/#comments</comments>
		<pubDate>Thu, 15 Mar 2012 17:59:38 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[coverage]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://darkcoding.ge1.ca/?p=1469</guid>
		<description><![CDATA[Getting unit test code coverage in python, and in django, is easy thanks to coverage: pip install coverage coverage run manage.py test app1 app2 app3 coverage html --include="my_project/*" www-browser htmlcov/index.html A disadvantage of Django&#8217;s test runner is that by default it runs tests for all the packages in INSTALLED_APPS. Usually you only want to run [...]]]></description>
			<content:encoded><![CDATA[<p>Getting unit test code coverage in python, and in django, is easy thanks to <a href="http://pypi.python.org/pypi/coverage" target="_blank" class="external">coverage</a>:</p>

<pre><code>pip install coverage
coverage run manage.py test app1 app2 app3
coverage html --include="my_project/*"
www-browser htmlcov/index.html
</code></pre>

<p>A disadvantage of Django&#8217;s test runner is that by default it runs tests for all the packages in INSTALLED_APPS. Usually you only want to run tests for your apps, not for third-party libraries. Hence I prefer the test runner in <a href="http://pypi.python.org/pypi/django-jenkins" target="_blank" class="external">django-jenkins</a>:</p>

<pre><code>pip install django-jenkins
</code></pre>

<p>Edit <code>settings.py</code> to add these lines, changing &#8220;my_project&#8221; in the last line to your project&#8217;s top level package name:</p>

<pre><code>INSTALLED_APPS += ('django_jenkins',)
JENKINS_TASKS = ('django_jenkins.tasks.django_tests',)
PROJECT_APPS = [appname for appname in INSTALLED_APPS if appname.startswith('my_project')]
</code></pre>

<p>Now run coverage with the <code>jtest</code> command, and it will always include all your apps, and only your apps:</p>

<pre><code>coverage run manage.py jtest
coverage html --include="my_project/*"
www-browser htmlcov/index.html
</code></pre>

<p>As the name implies, django-jenkins is also a great choice if you&#8217;re using continuous integration server <a href="http://jenkins-ci.org/" target="_blank" class="external">Jenkins</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/software/code-coverage-in-django-with-coverage-and-django-jenkins/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>In-memory key-value store in C, Go and Python</title>
		<link>http://www.darkcoding.net/software/in-memory-key-value-store-in-c-go-and-python/</link>
		<comments>http://www.darkcoding.net/software/in-memory-key-value-store-in-c-go-and-python/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 05:00:08 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[hashmap]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://darkcoding.ge1.ca/?p=1445</guid>
		<description><![CDATA[On paternity leave for my second child, I found myself writing an in-memory hashmap (a poor-man&#8217;s memcached), in Go, Python and C. I was wondering how hard it would be to replace memcached if we wanted to do something unusual with our key-value store. I also wanted to compare my knowledge of the languages, and, [...]]]></description>
			<content:encoded><![CDATA[<p>On paternity leave for my second child, I found myself writing an in-memory hashmap (a poor-man&#8217;s memcached), in Go, Python and C. I was wondering how hard it would be to replace memcached if we wanted to do something unusual with our key-value store. I also wanted to compare my knowledge of the languages, and, well, I get bored easily!</p>

<p><strong>The code is on <a href="https://github.com/grahamking/Key-Value-Polyglot" target="_blank" class="external">github as Key-Value-Polyglot</a>.</strong></p>

<p>Each version implements enough of the <code>get</code> and <code>set</code> commands from the <a href="http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt" target="_blank" class="external">memcached protocol</a> that we can test them with a memcached client.</p>

<h2>The wonderful Internet</h2>

<p><strong>Thanks to a great discussion <a href="http://news.ycombinator.com/item?id=3733090" target="_blank" class="external">on Hacker News</a>, in the comments here, and <a href="http://www.reddit.com/r/golang/duplicates/r5bkj/inmemory_keyvalue_store_in_c_go_and_python/" target="_blank" class="external">on reddit</a>, I have heavily updated this post.</strong> You&#8217;re reading the new improved version.</p>

<p>Having the Internet review your code is humbling. It is also an amazing way to learn. The code, and my knowledge, have improved tremendously thanks to the feedback.</p>

<p><span id="more-1445"></span></p>

<p>So far wonderful folks have contributed versions in <a href="https://github.com/grahamking/Key-Value-Polyglot/blob/master/Memg.java" target="_blank" class="external">Java</a>, <a href="https://github.com/grahamking/Key-Value-Polyglot/blob/master/MemG.scala" target="_blank" class="external">Scala</a>, <a href="https://github.com/grahamking/Key-Value-Polyglot/blob/master/memg.hs" target="_blank" class="external">Haskell</a>, <a href="https://github.com/grahamking/Key-Value-Polyglot/blob/master/memg.js" target="_blank" class="external">Node.js</a>, <a href="https://github.com/grahamking/Key-Value-Polyglot/blob/master/em_memcached.rb" target="_blank" class="external">Ruby (event machine)</a>, <a href="https://github.com/grahamking/Key-Value-Polyglot/blob/master/memg_gevent.py" target="_blank" class="external">Python gevent</a> and <a href="https://github.com/grahamking/Key-Value-Polyglot/blob/master/memg-diesel.py" target="_blank" class="external">Python diesel</a>. If you write a version in a different language (see Spec at bottom), please send it to me, either directly or as a pull-request on github. I&#8217;ll add it to the repo.</p>

<h1>Networking</h1>

<p><strong>Respond to each request with a single write. Or switch TCP_NODELAY on.</strong></p>

<p>I initially thought the Go version was many times faster than the C and Python versions, but that was due to quirks in my implementation.</p>

<p>The C and Python versions were doing multiple small writes to respond to each &#8220;get&#8221; request. On the server side <a href="http://en.wikipedia.org/wiki/Nagle's_algorithm" target="_blank" class="external">Nagle&#8217;s algorithm</a> was buffering those small writes, waiting for an ACK from the client of it&#8217;s previous send. On the client side, <a href="http://en.wikipedia.org/wiki/TCP_delayed_acknowledgment" target="_blank" class="external">Delayed ACKs</a> meant the client wasn&#8217;t sending the needed acknowledgment until a timeout. A textbook case, assuming you know about that textbook.</p>

<p>The solution was to combine those multiple writes into a single one. An alternative solution would be to switch on <a href="http://www.unixguide.net/network/socketfaq/2.16.shtml" target="_blank" class="external">TCP_NODELAY</a>.</p>

<p>The Go version didn&#8217;t require me to know about TCP_NODELAY, which I appreciated.</p>

<p>Internally, Go sets the socket to be non-blocking and uses <a href="http://www.kernel.org/doc/man-pages/online/pages/man7/epoll.7.html" target="_blank" class="external">epoll</a> and <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/futex.2.html" target="_blank" class="external">futex</a> to wait for data. Memcached does the same thing, via <a href="http://en.wikipedia.org/wiki/Libevent" target="_blank" class="external">libevent</a>. I only used a single client, and the implementations are not thread-safe, so these don&#8217;t matter right now. They should matter with a large number of clients.</p>

<h2>Writing it: Layers over Unix</h2>

<p><strong>Sockets:</strong> Our languages are wrapping POSIX <a href="http://www.kernel.org/doc/man-pages/online/pages/man7/socket.7.html" target="_blank" class="external">socket</a> system calls. C maps the calls exactly, and Python maps the C calls very closely. Go does a bit more work for us, replacing socket-bind-listen-accept with just listen-accept.</p>

<p><strong>Multiple concurrent requests:</strong> Go has the magic <a href="http://golang.org/doc/go_spec.html#Go_statements" target="_blank" class="external">go</a> statement, Python has the <a href="http://docs.python.org/library/threading.html" target="_blank" class="external">threading</a> library, and C has <a href="http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_create.3.html" target="_blank" class="external">pthread_create</a>. None of my  implementations are thread safe (thanks <a href="http://news.ycombinator.com/item?id=3733221" target="_blank" class="external">timtadh on HN</a>).</p>

<p><strong>Read buffering:</strong> Managing the data you get from the socket was easy, once commenters taught me about C&#8217;s <code>fdopen</code>. Sockets are just streams of data, it&#8217;s up to the protocol to say when a message starts and ends. For the memcached protocol, we need to be able to read until \r\n, and also read a specific amount of bytes (which might include \r\n).</p>

<p>Go has the <a href="http://golang.org/pkg/bufio/" target="_blank" class="external">bufio</a> package. C lets you treat a socket as a file, thanks to <a href="http://www.kernel.org/doc/man-pages/online/pages/man3/fdopen.3.html" target="_blank" class="external">fdopen</a>. Python does the same thing with <a href="http://docs.python.org/library/socket.html#socket.socket.makefile" target="_blank" class="external">socket.makefile</a>, which presumably wraps fdopen.</p>

<p>My C is rusty, so that version took me the longest to write, and is the least legible. The biggest slowdown was because I originally implemented buffering around the socket &#8216;recv&#8217; call. Commenters (thanks kbob) pointed out I didn&#8217;t need to do that, and I replaced it.</p>

<p>The Python version took me a while to get right, and that&#8217;s mostly my fault. I knew Python wouldn&#8217;t make me write my own buffering code, and I spent too long playing with timeout and non-blocking setups. Once I realized I could treat the socket as a file (&#8216;makefile&#8217;) things got easier.</p>

<p>Python 3&#8242;s universal newline support kindly normalizes \r\n to \n, but we&#8217;re disabling it here to preserve python 2 compatibility.</p>

<p>The Go version was the easiest to write because I had already used the bufio package, which solves our stream buffering problem.</p>

<p>Read on for how to build and profile the different versions yourself.</p>

<hr />

<h2>Build</h2>

<ul>
<li><p>Go version:
You&#8217;ll need a recent weekly snapshot of Go (<code>hg update weekly</code>), or Go v1 if it is released by the time you read this. Run it with: <code>go run memg.go</code>, or compile it with <code>go build memg.go</code> and run the executable it makes.</p></li>
<li><p>Python version:
Uses Python 2.7 or Python 3, just run the script.</p></li>
<li><p>C version:
Build with <code>gcc -std=gnu99 -g -W -Wall -pedantic -pthread -o memg memg.c</code>. There should be no warnings.</p></li>
</ul>

<h2>Timing</h2>

<p>This is explicitly not a benchmark, except if the question is <em>&#8220;what can an average programmer do in a few hours?&#8221;</em>.</p>

<p>All the versions perform about the same for me, and any differences are probably more due to my implementation than anything inherent in the languages. As <a href="http://news.ycombinator.com/item?id=3733553" target="_blank" class="external">antirez</a> said in the Hacker News comments:</p>

<blockquote>
  <p>In order to perform such a comparison you can&#8217;t write three small throw-away programs, you need to optimize each version at your best for weeks to start to be meaningful, and you need an expert in the three systems.</p>
</blockquote>

<p>To time the different versions on your machine run: <code>time python test.py</code>. That script requires python 2 and pylibmc (<code>pip install pylibmc</code> or <code>sudo apt-get install python-pylibmc</code>).</p>

<p>Try test.py against memcached too.</p>

<h2>Profiling</h2>

<p>To make profiling easier, each version accepts a <code>--single</code> command line parameter, so that it exits after a single connection.</p>

<p><code>strace</code> was very useful for inspecting all the versions (<code>strace -T</code> and <code>strace -c</code>). Run the following for a summary of the system calls issued, and run test.py in a different window.</p>

<pre><code>strace -c &lt;the memg version you want&gt; --single
</code></pre>

<h4>Python</h4>

<p>Start it in single mode, under the profiler:</p>

<pre><code>python -m cProfile -o stats memg.py --single
</code></pre>

<p>Run <code>test.py</code> in a different window.
View the output with pstats:</p>

<pre><code>$ python
&gt; import pstats
&gt; p = pstats.Stats("stats")
&gt; p.strip_dirs().sort_stats("cumulative").print_stats(20)
</code></pre>

<h4>Go</h4>

<p>Build an executable: <code>go build memg.go</code>. Run memg under prof, with <code>--single</code> so that it exits after the test connection closes:</p>

<pre><code>go tool prof memg --single
</code></pre>

<p>See: <a href="http://weekly.golang.org/cmd/prof/" target="_blank" class="external">prof command</a></p>

<p>You can get more detail using the <a href="http://golang.org/pkg/runtime/pprof/" target="_blank" class="external">runtime/pprof</a> package and <code>go tool pprof</code> to examine the created file.</p>

<h4>C</h4>

<p>C has Valgrind, and it&#8217;s callgrind tool is very nice:</p>

<pre><code>valgrind --tool=callgrind ./memg --single
</code></pre>

<p>Run <code>test.py</code> in a different window.
View the output with <code>kcachegrind</code>:</p>

<pre><code>kcachegrind callgrind.out.&lt;num&gt;
</code></pre>

<h2>Spec</h2>

<p>If you&#8217;re interested in trying it in a different language, or a different approach, here&#8217;s the short spec.</p>

<p>The key-value stores are an in-memory hash map. The listen on port 11211, and accept <code>set</code> and <code>get</code> commands, so that you can reproduce the following telnet interaction:</p>

<pre><code>telnet 127.0.0.1 11211

set greeting 0 0 11     # User
Hello World             # User, 11 bytes
STORED                  # Server response
get greeting            # User
VALUE greeting 0 11     # Server response
Hello World             # Server response
END                     # Server response
</code></pre>

<p>You type the &#8216;set&#8217;, &#8216;Hello World&#8217; and &#8216;get&#8217; lines. The rest are replies.
In the &#8216;set&#8217; line, the &#8217;11&#8242; is the length of the value (&#8216;Hello World&#8217;) in bytes. The two zero&#8217;s are ignored. All lines terminate with \r\n.</p>

<p>The repo has a <code>test.py</code> script which uses pylibmc. To get pylibmc:</p>

<ul>
<li><code>sudo pip install pylibmc</code></li>
<li>OR <code>sudo apt-get install python-pylibmc</code></li>
</ul>

<p>If you make a version in a different language, please send it to me on github, or link it in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/software/in-memory-key-value-store-in-c-go-and-python/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Go after four months #golang</title>
		<link>http://www.darkcoding.net/software/go-lang-after-four-months/</link>
		<comments>http://www.darkcoding.net/software/go-lang-after-four-months/#comments</comments>
		<pubDate>Wed, 29 Feb 2012 02:56:34 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[golang]]></category>

		<guid isPermaLink="false">http://darkcoding.ge1.ca/?p=1389</guid>
		<description><![CDATA[I&#8217;ve been using the Go programming language for over four months in my spare time, mainly to write an IRC client (hatcog) &#8211; here is my trip report. Go sits somewhere between C and Python. It has the static type checking and bit-twiddling powers of C (and pointers!), yet much of the speed of development [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using the <a href="http://golang.org" target="_blank" class="external">Go</a> programming language for over four months in my spare time, mainly to write an IRC client (<a href="https://github.com/grahamking/hatcog" target="_blank" class="external">hatcog</a>) &#8211; here is my trip report.</p>

<p>Go sits somewhere between C and Python. It has the static type checking and bit-twiddling powers of C (and pointers!), yet much of the speed of development and conciseness of Python (e.g. string split and join). Bruce Eckel called it a language <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=333589" target="_blank" class="external">designed to create servers</a>, and I agree wholeheartedly.</p>

<p><span id="more-1389"></span></p>

<p>Go is a C family language, both in the sense that it looks like C, and in the sense that you can easily call C libraries. Here is hello world:</p>

<pre><code>package main;

import "fmt"

func main() {
    fmt.Println("Hello World!");
}
</code></pre>

<h2>Interlude: Cooking up Go</h2>

<p>This is what I think the recipe for Go looked like:</p>

<ol>
<li><p>Go back to the 70s / 80s and find a bunch of great programmers. Say, <a href="http://en.wikipedia.org/wiki/Ken_Thompson" target="_blank" class="external">Ken Thompson</a>, <a href="http://en.wikipedia.org/wiki/Rob_Pike" target="_blank" class="external">Rob Pike</a>, people like that. Marinate them in Bell Labs for 30 years, during which time they code in C, keep developing Unix, invent Plan 9, <a href="http://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt" target="_blank" class="external">UTF-8</a>, and other wonderful things.</p></li>
<li><p>Take them out, seduce them with Python, wow them with Google-scale computing. Add more amazing programmers (<a href="http://en.wikipedia.org/wiki/Brad_Fitzpatrick" target="_blank" class="external">Brad Fitzpatrick</a> for example), stir in Google&#8217;s near-unlimited resources.</p></li>
<li><p>Ask them how they would do C now, if they could start from scratch.</p></li>
</ol>

<h2>Observations</h2>

<p>The C legacy is very strong in Go, and not just in the curly braces. For example object-orientation is done with a <a href="http://golangtutorials.blogspot.com/2011/06/structs-in-go-instead-of-classes-in.html" target="_blank" class="external">struct plus some methods</a>.</p>

<p>Capitalization is significant. The visibility of a name outside a package is determined by whether its first character is upper case.</p>

<p>Multiple return values instead of <a href="http://golang.org/doc/go_faq.html#exceptions" target="_blank" class="external">exceptions</a>. To signal an error occurred in your function you return the error, like in C, but you can return multiple values, like in Python. Error checking typically looks like this:</p>

<pre><code>retval, err := myFunc(param)
if err != nil {
    // handle it
}
</code></pre>

<p>The style guide is whatever program <strong>gofmt</strong> says it is. It will often just fix it for you. Use whatever style you want, then run it through gofmt before checking-in.</p>

<p>Interfaces, with no explicit implementations. If you have the methods of that interface, you count. That gives statically checked duck typing. Lovely.</p>

<p>Go has arrays, but you usually use slices instead. A slice works like a Python slice, but internally it&#8217;s a smart pointer to an array, and has a different type (which matters because we&#8217;re doing static typing remember). The array is it&#8217;s backing storage. I found this tricky to understand at first.</p>

<p>Everything is passed by value: Objects (structs) and Arrays are copied before being passed. For arrays it doesn&#8217;t matter because you&#8217;re usually passing slices (which wrap pointers &#8211; as do maps). When defining your own types, you have to remember to always pass a pointer.</p>

<p>The compiler is strict: Unused variables are a compiler error.</p>

<h2>Negatives</h2>

<p>The one big potential negative is that it&#8217;s compiled. In Python I often find myself stepping into third party libraries. Always having the source code is fantastic. One print statement deep in a someone else&#8217;s code can really help comprehension. No being able to do this in Java was a problem. I don&#8217;t have enough experience with Go to say if this will be a problem during debugging or not.</p>

<p>A <a href="http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop" target="_blank" class="external">read-eval-print loop</a> would have made learning Go much easier. I can&#8217;t overstate how often I try out simple commands, like date formatting, in <a href="http://ipython.org/" target="_blank" class="external">ipython</a>. In Java I used <a href="http://www.beanshell.org/" target="_blank" class="external">beanshell</a>.</p>

<p>You can&#8217;t daemonize, because of the way go-routines work. This could be fixed soon, see <a href="http://groups.google.com/group/golang-nuts/browse_thread/thread/2b29d93b90501a4b/95242bfb7ae0549e" target="_blank" class="external">Russ Cox&#8217;s message here</a>. In practice I usually use <a href="http://upstart.ubuntu.com/" target="_blank" class="external">Upstart</a>, so it doesn&#8217;t cause a problem.</p>

<p>Go has an un-googlable name. The convention is to use <em>golang</em> as a search term.</p>

<p>The language is still very young and in flux. See for example the GitHub network for <a href="https://github.com/jabb/gocurse/network" target="_blank" class="external">gocurse</a>. v1 of Go is due in the first half of this year (2012), so hopefully things will settle down.</p>

<p>The extremely useful string manipulation methods are all in the <a href="http://golang.org/pkg/strings/" target="_blank" class="external">strings</a> package, instead of being methods on the string object. There are objects in many packages, so there is no doubt a very good reason for string not having these methods. That&#8217;s the thing about Go, there&#8217;s usually <a href="http://golang.org/doc/docs.html" target="_blank" class="external">a very good reason for everything it does</a>. Learning Go is an education. Oh, that&#8217;s a positive.</p>

<h2>Positives</h2>

<blockquote>
  <p>Old programs read like quiet conversations between a well-spoken research worker and a well-studied mechanical colleague, not as a debate with a compiler
  &#8211; Dick Gabriel.</p>
</blockquote>

<p>Russ Cox uses that Dick Gabriel quote to illustrate what they are aiming for with Go. In some hard-to-define way, Go feels serious and grown up. It has high expectations of you.</p>

<p>A familiar language. As a Python programmer with a Java and C background, I was productive very fast.</p>

<p>A modern language. Go has everything you&#8217;d expect a modern language to have: Unicode, garbage collection, multi-core (GOMAXPROCS), built-in map, string and array types, closures, unit-testing , an official style guide (&#8216;gofmt&#8217;), reflection, etc</p>

<p>The documentation is excellent, and usually available from the command line: <code>godoc &lt;package&gt;</code>.</p>

<p>The compiler is very fast, fast enough that you can use Go as a scripting language. Use <a href="https://wiki.ubuntu.com/gorun" target="_blank" class="external">gorun</a> as your hash-bang line.</p>

<p>Static typing makes programming easier. That is a debatable point, but it does for me. Static typing makes code easier to read, and make me feel a little more comfortable that things won&#8217;t go boom in the middle of the night.</p>

<h2>Concurrency</h2>

<p>The one big NEW (to me at least) thing Go does very well is concurrency. The keyword <code>go</code> starts a new go-routine. That&#8217;s what you use instead of sub-processes, threads, or co-routines. The go-routine might run on the same core / processor as your current one, or it might not. You don&#8217;t worry about that.</p>

<p>Go-routine&#8217;s communicate on channels. You epoll those channels using the <code>select</code> keyword.</p>

<p>Here is the heart of hatcog, my IRC client. A go-routine listens on the port connected to the server and puts incoming data on channel <code>fromServer</code>. Another go-routine listens for keyboard input, and puts that on channel <code>fromUser</code>. The middle bit watches both channels:</p>

<pre><code>for self.isRunning {

    select {
    case serverData, ok = &lt;-fromServer:
        if ok {
            self.onServer(serverData)
        } else {
            self.isRunning = false
        }

    case userInput, ok = &lt;-fromUser:
        if ok {
            self.onUser(userInput)
        } else {
            self.isRunning = false
        }
    }

}
</code></pre>

<p>More details on <a href="http://golang.org/doc/effective_go.html#concurrency" target="_blank" class="external">Go&#8217;s concurrency model</a></p>

<p>Do you see how that makes servers so much easier? You could write a <a href="http://golang.org/doc/codelab/wiki/" target="_blank" class="external">webapp that&#8217;s it&#8217;s own server</a>. The &#8220;C10K problem&#8221; might not be a problem at all.</p>

<h2>Conclusion</h2>

<p>Would I be happy working with Go as my main language? Yes, I would. It&#8217;s a joy to work with, and I got productive very fast.</p>

<p>Am I using it instead of Python for all my new projects? No, I&#8217;m not. There are two reasons for that. Firstly, it&#8217;s a very young language, so library availability is limited (for example, I need curses). Second, well, Python is just so amazing.</p>

<p>If I was still doing Java, or (heaven forbid) C++, I would invest heavily in Go. It was designed to replace them, and it does that well.</p>

<p>As a Python guy, the summary is more nuanced. I see the benefit of static typing. Other claimed benefits of Go over Python are that it&#8217;s faster, and that it&#8217;s &#8220;better at scale&#8221;.</p>

<p>For some things I&#8217;ve done Go has been faster, for other things Python. The biggest difference is probably in how well I write the code. Although I love speed in principle, nothing I do is CPU bound.</p>

<p>The &#8220;better at scale&#8221; argument doesn&#8217;t really apply to what I do for a living, which is building webapps with Django. We scale performance-wise by adding servers, and code-wise by adding small self-contained &#8216;apps&#8217; (in the Django sense).</p>

<p>Go&#8217;s sweet spot is building servers. It makes concurrency safer and easier than the current options. I&#8217;m going to keep using it for that. And because it&#8217;s fun.</p>

<p>Next you might want to page through this <a href="http://golang.org/doc/ExpressivenessOfGo.pdf" target="_blank" class="external">Go presentation</a>, or dive in to the (rather academic) <a href="http://golang.org/doc/go_tutorial.html" target="_blank" class="external">tutorial</a>.</p>

<p>(Did I make a mistake? Please correct me in the comments. Thanks!)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/software/go-lang-after-four-months/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Who we are. Why we do it.</title>
		<link>http://www.darkcoding.net/society/who-we-are-why-we-do-it/</link>
		<comments>http://www.darkcoding.net/society/who-we-are-why-we-do-it/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 00:37:13 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Society]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://darkcoding.ge1.ca/?p=1407</guid>
		<description><![CDATA[A year here and he still dreamed of cyberspace, hope fading nightly. All the speed he took, all the turns he&#8217;d taken and the corners he&#8217;d cut in Night City, and still he&#8217;d see the matrix in his sleep, bright lattices of logic unfolding across that colorless void&#8230; The Sprawl was a long strange way [...]]]></description>
			<content:encoded><![CDATA[<blockquote>
  <p>A year here and he still dreamed of cyberspace, hope fading nightly. All the speed he took, all the turns he&#8217;d taken and the corners he&#8217;d cut in Night City, and still he&#8217;d see the matrix in his sleep, bright lattices of logic unfolding across that colorless void&#8230; The Sprawl was a long strange way home over the Pacific now, and he was no console man, no cyberspace cowboy. Just another hustler, trying to make it through.</p>
  
  <p>But the dreams came on in the Japanese night like livewire voodoo, and he&#8217;d cry for it, cry in his sleep, and wake alone in the dark, curled in his capsule in some coffin hotel, his hands clawed into the bedslab, temperfoam bunched between his fingers, trying to reach the console that wasn&#8217;t there.</p>
</blockquote>

<p>From <a href="http://www.williamgibsonbooks.com/books/neuromancer.asp" target="_blank" class="external">Neuromancer</a>, p4-5</p>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/society/who-we-are-why-we-do-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Miami Vice: Off-duty</title>
		<link>http://www.darkcoding.net/misc/miami-vice-off-duty/</link>
		<comments>http://www.darkcoding.net/misc/miami-vice-off-duty/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 04:13:26 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[miami vice]]></category>
		<category><![CDATA[movie]]></category>
		<category><![CDATA[story]]></category>

		<guid isPermaLink="false">http://darkcoding.ge1.ca/?p=1395</guid>
		<description><![CDATA[Someone once told me that interesting stories start like this: Establish what &#8220;normal&#8221; looks like in your world. If your story is set in present-day New York, you can do that quickly, during the opening credits. If your story is set in Middle Earth, it takes a lot longer. Break the routine. Frodo has to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.the-spontaneity-shop.com/workshops/course_dates.html" target="_blank" class="external">Someone</a> once told me that interesting stories start like this:</p>

<ol>
<li>Establish what &#8220;normal&#8221; looks like in your world. If your story is set in present-day New York, you can do that quickly, during the opening credits. If your story is set in <a href="http://en.wikipedia.org/wiki/The_Lord_of_the_Rings" target="_blank" class="external">Middle Earth</a>, it takes a lot longer.</li>
<li>Break the routine. Frodo has to leave the shire. This is when the story really starts, and why you&#8217;re watching it. Today is different.</li>
</ol>

<p>The remake of the classic 80s series, <a href="http://www.imdb.com/title/tt0430357/" target="_blank" class="external">Miami Vice (2006)</a>, fails at number 2. For the whole film, two undercover vice squad detectives go undercover to bust a vice gang. Sure there&#8217;s fast cars, guns, all that, but it could of been so much better.</p>

<p><span id="more-1395"></span>
About fifteen minutes into the movie, Sonny and Ricardo (the protagonists) are talking to an informer by the side of the motorway. The informer walks in front of a truck and dies right in front of the detectives. In any real police force they would have immediately been put on sick leave, with counselling. <em>That&#8217;s</em> a break in the routine, and that&#8217;s the movie I want to see.</p>

<p>You could make it very dark. One of them goes back to work in a few days, leaves the story. The other, the focus, stays on sick leave. He realises he&#8217;s spent his whole live at work, often pretending to be someone else. No family, no friends, no community, no interests, and a very uncertain sense of identity. He mows his lawn. He slowly falls apart.</p>

<p>But it needn&#8217;t be dark. Our hero mows the lawn, and gets to know the lives of people on his street. He gets caught up in an intrigue that uses his elite vice-squadding skills. Something much below his usual level of investigation, but something that matters to this community. Maybe the old ladies&#8217; house is going to be foreclosed by the bank. Whatever the <a href="http://en.wikipedia.org/wiki/MacGuffin" target="_blank" class="external">plot device</a> is, it allows our protagonist to change, to gain a new perspective on life.</p>

<p>A gardener going undercover to bust a crime ring is an interesting story. An undercover cop going undercover, isn&#8217;t. Stories are interesting when they change the people in them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/misc/miami-vice-off-duty/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>In Go, is your terminal a console or a pipe? isatty golang</title>
		<link>http://www.darkcoding.net/software/in-go-is-your-terminal-a-console-or-a-pipe-isatty-golang/</link>
		<comments>http://www.darkcoding.net/software/in-go-is-your-terminal-a-console-or-a-pipe-isatty-golang/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 17:08:20 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[isatty]]></category>

		<guid isPermaLink="false">http://www.darkcoding.net/?p=1334</guid>
		<description><![CDATA[Is my terminal connected to the console, or to a pipe? // Is given File a terminal? func isatty(file *os.File) bool { stat, _ := file.Stat() return !stat.IsFifo() } if ! isatty(os.Stdin) { // read what was piped in } For example: $ ./myprog # isatty = yes $ echo "boo" &#124; ./myprog # isatty [...]]]></description>
			<content:encoded><![CDATA[<p>Is my terminal connected to the console, or to a pipe?</p>

<pre><code>// Is given File a terminal?
func isatty(file *os.File) bool {
    stat, _ := file.Stat()
    return !stat.IsFifo()
}

if ! isatty(os.Stdin) {
  // read what was piped in
}
</code></pre>

<p>For example:</p>

<pre><code>$ ./myprog                # isatty = yes
$ echo "boo" | ./myprog   # isatty = no
</code></pre>

<p>Mirrors the behaviour of Python&#8217;s <a href="http://docs.python.org/library/os.html#os.isatty" target="_blank" class="external">isatty</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/software/in-go-is-your-terminal-a-console-or-a-pipe-isatty-golang/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Proxy socket.io and nginx on the same port, over SSL</title>
		<link>http://www.darkcoding.net/software/proxy-socket-io-and-nginx-on-the-same-port-over-ssl/</link>
		<comments>http://www.darkcoding.net/software/proxy-socket-io-and-nginx-on-the-same-port-over-ssl/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 22:32:26 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[haproxy]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[node]]></category>
		<category><![CDATA[socket.io]]></category>
		<category><![CDATA[ssl]]></category>
		<category><![CDATA[stunnel]]></category>
		<category><![CDATA[web socket]]></category>

		<guid isPermaLink="false">http://darkcoding.ge1.ca/?p=1343</guid>
		<description><![CDATA[My current project has a realtime part, using socket.io on nodejs, and a web part using django on nginx / gunicorn. Here&#8217;s a setup to put them both on the same port, and make them both go over SSL. I&#8217;m assuming you&#8217;re on Ubuntu. Disclaimer: I got this working last night, so no promises. You&#8217;ll [...]]]></description>
			<content:encoded><![CDATA[<p>My current project has a realtime part, using <a href="http://socket.io/" target="_blank" class="external">socket.io</a> on <a href="http://nodejs.org/" target="_blank" class="external">nodejs</a>, and a web part using <a href="https://www.djangoproject.com/" target="_blank" class="external">django</a> on nginx / gunicorn. Here&#8217;s a setup to put them both on the same port, and make them both go over SSL. I&#8217;m assuming you&#8217;re on Ubuntu.</p>

<p><em>Disclaimer</em>: I got this working last night, so no promises. You&#8217;ll certainly want to tweak haproxy&#8217;s config for performance. I also only tested it with socket.io&#8217;s web socket transport.</p>

<h2>Overview</h2>

<p><a href="http://www.darkcoding.net/files/2011/12/socketio_web_same_port.png"><img src="http://www.darkcoding.net/files/2011/12/socketio_web_same_port.png" alt="" title="socketio_web_same_port" width="600" height="120" class="alignnone size-full wp-image-1344" /></a></p>

<ul>
<li><a href="http://www.stunnel.org/" target="_blank" class="external">stunnel</a> decrypts the ssl, so everything after that doesn&#8217;t know about it. It decrypts both web traffic (HTTPS to HTTP), and web socket traffic (WSS to WS).</li>
<li><a href="http://haproxy.1wt.eu/" target="_blank" class="external">haproxy</a> sends web socket traffic to node and web traffic to nginx.</li>
<li>node runs socket.io, handling the web socket traffic.</li>
<li>nginx serves static content.</li>
<li>gunicorn runs python / django, and there&#8217;s a database out back somewhere, but that&#8217;s not relevant here.</li>
</ul>

<p>Currently nginx doesn&#8217;t <span id="more-1343"></span> support HTTP/1.1 for it&#8217;s backends, so it can&#8217;t proxy web socket traffic. That&#8217;s why we have haproxy.<br />
But haproxy doesn&#8217;t do SSL, that&#8217;s why we have stunnel.<br />
And haproxy isn&#8217;t a web server, so we still need nginx.</p>

<h2>Generate a self-signed cert</h2>

<p>To test this you&#8217;ll need an SSL certificate. Here&#8217;s how (thanks <a href="http://www.phpmag.ru/2009/08/12/how-to-create-self-signed-ssl-certificate/" target="_blank" class="external">Victor Farazdagi</a>):</p>

<pre><code>openssl genrsa -out mysite.key 1024
openssl req -new -key mysite.key -out mysite.csr  # common name == your domain
openssl x509 -req -days 365 -in mysite.csr -signkey mysite.key -out mysite.crt
</code></pre>

<h2>stunnel</h2>

<p>Install: <code>sudo apt-get install stunnel4</code>.<br />
Enable it by editing <code>/etc/default/stunnel</code> and settings <code>ENABLED=1</code>.</p>

<p>Config: /etc/stunnel/stunnel.conf</p>

<pre><code>cert = /etc/stunnel/localhost.crt
key = /etc/stunnel/localhost.key

debug = 5
output = /var/log/stunnel4/stunnel.log

[https]
accept = 443
connect = 81
TIMEOUTclose = 0
</code></pre>

<h2>haproxy</h2>

<p>Install: <code>sudo apt-get install haproxy</code></p>

<p>Config: /etc/haproxy/haproxy.cfg</p>

<pre><code>global
    maxconn 4096
    daemon

defaults
    mode http
    log 127.0.0.1 local1 debug
    option httplog

frontend all 0.0.0.0:81
    timeout client 86400000
    default_backend www_backend
    acl is_websocket hdr(Upgrade) -i WebSocket
    acl is_websocket path_beg /socket.io/

    use_backend socket_backend if is_websocket

backend www_backend
    balance roundrobin
    option forwardfor # This sets X-Forwarded-For
    option httpclose
    timeout server 30000
    timeout connect 4000
    server server1 localhost:82 weight 1 maxconn 1024 check

backend socket_backend
    balance roundrobin
    option forwardfor # This sets X-Forwarded-For
    option httpclose
    timeout queue 5000
    timeout server 86400000
    timeout connect 86400000
    server server1 localhost:9000 weight 1 maxconn 1024 check
</code></pre>

<p>haproxy logs to syslog, and expects it to be in server mode, so you need to set that up too (thanks <a href="http://kevin.vanzonneveld.net/techblog/article/haproxy_logging/" target="_blank" class="external">Kevin van Zonneveld</a>):</p>

<p>rsyslog config: /etc/rsyslog.d/haproxy.conf</p>

<pre><code>$ModLoad imudp
$UDPServerRun 514
$UDPServerAddress 127.0.0.1

local1.* -/var/log/haproxy_1.log
&amp; ~ 
</code></pre>

<p>Then bounce rsyslog: <code>sudo restart rsyslog</code></p>

<h2>nginx</h2>

<p>First bounce http traffic to https: /etc/nginx/sites-enabled/default</p>

<pre><code>server {
  listen 80;
  server_name _; # Catch requests that don't match any other server name
  rewrite ^ https://myapp.example.com$request_uri? permanent;
}
</code></pre>

<p>Next setup nginx on port 82, and make sure to rewrite Location responses (see THIS ONE below):</p>

<pre><code>server {
  listen 82;
  server_name myapp.example.com;

  location /static {
    root /var/www/myapp.example.com;
  }

  location / {
    proxy_pass http://unix:/tmp/ginger-gunicorn.sock;
    ## THIS ONE ##
    proxy_redirect http://myapp.example.com https://myapp.example.com;
    ## END THIS ONE ##
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}
</code></pre>

<h2>Node</h2>

<p>Put node on port 9000, with a standard config. Make sure to ask the client library to connect securely, so that it stays on port 443 (https then wss):</p>

<pre><code>var socket = io.connect('https://myapp.example.com', {secure: true})
</code></pre>

<h2>Good luck</h2>

<p>This setup is working for me, so far. There&#8217;s quite a few moving parts. HTTP/1.1 is coming to nginx (it&#8217;s in the dev version already), so hopefully we&#8217;ll be able to use that instead of haproxy and stunnel soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/software/proxy-socket-io-and-nginx-on-the-same-port-over-ssl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Pretty command line / console output on Unix in Python and Go Lang</title>
		<link>http://www.darkcoding.net/software/pretty-command-line-console-output-on-unix-in-python-and-go-lang/</link>
		<comments>http://www.darkcoding.net/software/pretty-command-line-console-output-on-unix-in-python-and-go-lang/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 01:17:10 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[ansi]]></category>
		<category><![CDATA[commandline]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.darkcoding.net/?p=1317</guid>
		<description><![CDATA[There are lots of easy ways to improve the output of your command line scripts, without going full curses, such as single-line output, using bold text and colors, and even measuring the screen width and height. The examples are in Python, with a summary example in Go (golang) at the end. Single line with \r [...]]]></description>
			<content:encoded><![CDATA[<p>There are lots of easy ways to improve the output of your command line scripts, without going <a href="http://en.wikipedia.org/wiki/Ncurses" target="_blank" class="external">full curses</a>, such as single-line output, using bold text and colors, and even measuring the screen width and height.</p>

<p>The examples are in Python, with a summary example in Go (golang) at the end.</p>

<h2>Single line with \r (carriage return)</h2>

<p>Instead of printing a \n (which most &#8216;print&#8217; methods do by default), print a \r. That sends the cursor back to the beginning of the current line (carriage return), without dropping down to a new line (line feed).</p>

<pre><code>import time, sys
total = 10
for i in range(total):
    sys.stdout.write('%d / %d\r' % (i, total))
    sys.stdout.flush()
    time.sleep(0.5)
print('Done     ')
</code></pre>

<p><span id="more-1317"></span>
We do <code>sys.stdout.flush()</code> to flush the output, otherwise the operating system buffers it and you don&#8217;t see anything until the end. Note also the extra spaces after &#8216;Done&#8217;, to clear previous output. Remove them and you&#8217;ll see why they are needed.</p>

<h2>ANSI escape sequences</h2>

<p><a href="http://en.wikipedia.org/wiki/ANSI_escape_code" target="_blank" class="external">ANSI escape sequences</a> are special non-printable characters you send to the terminal to control it. When you do <code>ls --color</code>, ls is using ANSI escape sequences to pretty things up for you.</p>

<p>When the terminal receives an ESC character (octal 33 &#8211; see <code>man ascii</code>) it expects control information to follow, instead of printable data. Most escape sequences start with <code>ESC</code> and <code>[</code>.</p>

<h3>Bold</h3>

<p>To display something in bold, switch on the bright attribute (1), then reset it afterwards (0).</p>

<pre><code>def bold(msg):
    return u'\033[1m%s\033[0m' % msg

print('This is %s yes it is' % bold('bold'))
</code></pre>

<h3>Color</h3>

<p>There are 8 colors, ANSI codes 30 to 37, which can have the bold modifier, making 16 colors. Colors are <a href="http://en.wikipedia.org/wiki/ANSI_escape_code#Colors" target="_blank" class="external">surprisingly consistent across terminals</a>, but can usually be changed by the user.</p>

<pre><code>def color(this_color, string):
    return "\033[" + this_color + "m" + string + "\033[0m"

for i in range(30, 38):
    c = str(i)
    print('This is %s' % color(c, 'color ' + c))

    c = '1;' + str(i)
    print('This is %s' % color(c, 'color ' + c))
</code></pre>

<p>If that's not enough for you, you can have 256 colors (thanks <a href="http://lucentbeing.com/blog/that-256-color-thing/" target="_blank" class="external">lucentbeing</a>), but only if your terminal is set to 256 color mode. You usually get 256 colors by putting one of these lines in your <code>.bashrc</code>:</p>

<pre><code>export TERM='screen-256color'   # Use this is you use tmux or screen. Top choice!
export TERM='xterm-256color'    # Use this otherwise
</code></pre>

<p>Here's lots of colors (copy <code>color</code> function from above):</p>

<pre><code>for i in range(256):
    c = '38;05;%d' % i
    print( color(c, 'color ' + c) )
</code></pre>

<h3>Clear the screen</h3>

<p>A pair of ANSI escape sequences:</p>

<pre><code>import sys

def clear():
    """Clear screen, return cursor to top left"""
    sys.stdout.write('\033[2J')
    sys.stdout.write('\033[H')
    sys.stdout.flush()

clear()
</code></pre>

<h3>More ANSI power</h3>

<p>You can do lots more with ANSI escape sequences, such as change the background color, move the cursor around, and even make it blink. Use your power wisely.</p>

<h2>Measure the screen</h2>

<p>You can find out how many characters wide or lines high the current terminal is. From the command line, try <code>tput lines</code> or <code>tput cols</code>. To get the data direct from Unix:</p>

<pre><code>import sys
import fcntl
import termios
import struct

lines, cols = struct.unpack('hh',  fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, '1234'))
print('Terminal is %d lines high by %d chars wide' % (lines, cols))
</code></pre>

<p>This is making a system call, hence it's a bit inscrutable. It's requesting TIOCGWINSZ information, for file sys.stdout (the terminal), and then interprets it as two packed short integers (hh). The '1234' is just placeholder, which must be four chars long.</p>

<h2>A pretty progress bar</h2>

<p>Putting some of the above together, here's a progress bar.</p>

<pre><code>import sys
import fcntl
import termios
import struct
import time

COLS = struct.unpack('hh',  fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, '1234'))[1]

def bold(msg):
    return u'\033[1m%s\033[0m' % msg

def progress(current, total):
    prefix = '%d / %d' % (current, total)
    bar_start = ' ['
    bar_end = '] '

    bar_size = COLS - len(prefix + bar_start + bar_end)
    amount = int(current / (total / float(bar_size)))
    remain = bar_size - amount

    bar = 'X' * amount + ' ' * remain
    return bold(prefix) + bar_start + bar + bar_end

NUM = 100
for i in range(NUM + 1):
    sys.stdout.write(progress(i, NUM) + '\r')
    sys.stdout.flush()
    time.sleep(0.05)
print('\n')
</code></pre>

<p>That's it! Happy console scripts.</p>

<h1>And now the progress bar in Go <a href="http://golang.org" target="_blank" class="external">golang</a>, for fun</h1>

<pre><code>package main

import (
    "time"
    "os"
    "strconv"
    "strings"
    "syscall"
    "unsafe"
)

const (
    ONE_MSEC    = 1000 * 1000
    _TIOCGWINSZ = 0x5413    // On OSX use 1074295912. Thanks zeebo
    NUM         = 50
)

func main() {

    var bar string

    cols := TerminalWidth()

    for i := 1; i &lt;= NUM; i++ {
        bar = progress(i, NUM, cols)
        os.Stdout.Write([]byte(bar + "\r"))
        os.Stdout.Sync()
        time.Sleep(ONE_MSEC * 50)
    }
    os.Stdout.Write([]byte("\n"))
}

func Bold(str string) string {
    return "\033[1m" + str + "\033[0m"
}

func TerminalWidth() int {
    sizeobj, _ := GetWinsize()
    return int(sizeobj.Col)
}

func progress(current, total, cols int) string {
    prefix := strconv.Itoa(current) + " / " + strconv.Itoa(total)
    bar_start := " ["
    bar_end := "] "

    bar_size := cols - len(prefix + bar_start + bar_end)
    amount := int(float32(current) / (float32(total) / float32(bar_size)))
    remain := bar_size - amount

    bar := strings.Repeat("X", amount) + strings.Repeat(" ", remain)
    return Bold(prefix) + bar_start + bar + bar_end
}

type winsize struct {
    Row    uint16
    Col    uint16
    Xpixel uint16
    Ypixel uint16
}

func GetWinsize() (*winsize, os.Error) {
    ws := new(winsize)

    r1, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
        uintptr(syscall.Stdin),
        uintptr(_TIOCGWINSZ),
        uintptr(unsafe.Pointer(ws)),
    )

    if int(r1) == -1 {
        return nil, os.NewSyscallError("GetWinsize", int(errno))
    }
    return ws, nil
}
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/software/pretty-command-line-console-output-on-unix-in-python-and-go-lang/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>On why hackers don&#039;t work on large teams</title>
		<link>http://www.darkcoding.net/society/on-why-hackers-dont-work-on-large-teams/</link>
		<comments>http://www.darkcoding.net/society/on-why-hackers-dont-work-on-large-teams/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 00:05:10 +0000</pubDate>
		<dc:creator>graham</dc:creator>
				<category><![CDATA[Society]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.darkcoding.net/?p=1313</guid>
		<description><![CDATA[We&#8217;ve know for over 35 years that &#8220;adding manpower to a late software project makes it later&#8221;. Amazon has it&#8217;s two-pizza team heuristic: &#8220;If a project team can eat more than two pizzas, it&#8217;s too large&#8221;. The excellent Code Complete has a detailed explanation of how communication costs increase with team size. Yet we still [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve know for over 35 years that <a href="http://en.wikipedia.org/wiki/The_Mythical_Man-Month" target="_blank" class="external">&#8220;adding manpower to a late software project makes it later&#8221;</a>. Amazon has it&#8217;s two-pizza team heuristic: <a href="http://www.google.ca/search?q=two+pizza+team" target="_blank" class="external">&#8220;If a project team can eat more than two pizzas, it&#8217;s too large&#8221;</a>. The excellent <a href="http://www.amazon.com/gp/product/0735619670/ref=as_li_ss_tl?ie=UTF8&#038;tag=darkcoding-20&#038;linkCode=as2&#038;camp=217145&#038;creative=399369&#038;creativeASIN=0735619670">Code Complete</a>  has a detailed explanation of how communication costs increase with team size. Yet we still need reminding.</p>

<p>Dhanji R. Prasanna has an excellent <a href="http://rethrick.com/#mmm" target="_blank" class="external">retrospective on his time on the Google Wave team</a>. He sums up the problem with big teams very well:</p>

<blockquote>
  <p>And this is the essential broader point&#8211;as a programmer you must have a series of wins, every single day. It is the Deus Ex Machina of hacker success. It is what makes you eager for the next feature, and the next after that. And a large team is poison to small wins. The nature of large teams is such that even when you do have wins, they come after long, tiresome and disproportionately many hurdles. And this takes all the wind out of them.</p>
</blockquote>

<p>For me, that&#8217;s really the crux of it. As a programmer, it kills you to not get stuff done. Large teams necessarily involve more communication, more complexity, and less getting stuff done. Large teams are a programmers equivalent of retirement.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.darkcoding.net/society/on-why-hackers-dont-work-on-large-teams/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

