<?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>( f o o b a r . l u ) &#187; Python</title>
	<atom:link href="http://foobar.lu/wp/category/coding/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://foobar.lu/wp</link>
	<description>coding should be fun</description>
	<lastBuildDate>Sat, 19 May 2012 10:06:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>A comprehensive guide through Python packaging (a.k.a. setup scripts)</title>
		<link>http://foobar.lu/wp/2012/05/13/a-comprehensive-step-through-python-packaging-a-k-a-setup-scripts/</link>
		<comments>http://foobar.lu/wp/2012/05/13/a-comprehensive-step-through-python-packaging-a-k-a-setup-scripts/#comments</comments>
		<pubDate>Sun, 13 May 2012 13:03:39 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/?p=270</guid>
		<description><![CDATA[One of the really useful things in python are the setup scripts. When doing &#8220;serious&#8221; business, you really should look into them. Setup scripts are amazingly powerful. But they don&#8217;t necessarily need to be complex. But because of this flexibility, the documentation around them seems like a lot to read. Additionally, the state of packaging [...]]]></description>
			<content:encoded><![CDATA[<p>One of the really useful things in python are the setup scripts. When doing &#8220;serious&#8221; business, you <em>really</em> should look into them. Setup scripts are amazingly powerful. But they don&#8217;t necessarily need to be complex. But because of this flexibility, the documentation around them seems like a lot to read. Additionally, the state of packaging has changed quite a bit over the years. So you now have a couple of packages (distutils, setuptools, distribute) which all seem to try to solve the same problem. See <a title="The Current State of Packaging in Python" href="http://guide.python-distribute.org/introduction.html#current-state-of-packaging">the current state of packaging</a> for more details on this.</p>
<p>This post attempts to summarize the important bits using a &#8220;Hello World&#8221; project and steeping through the process of creating the <tt>setup.py</tt> file:</p>
<ul>
<li>Creating a package distribution</li>
<li>Automatic generation of executables</li>
<li>Version numbers</li>
<li>Dependency management</li>
<li>Publishing your package (thus also making it available for automatic dependency resolution)</li>
<li>Some more food for thought.</li>
</ul>
<div class="note admonition">
<strong>NOTE:</strong> The <tt>setup.py</tt> script we will construct in this post, will use two bits of code which may not work in all cases:</p>
<ul>
<li>importing the package itself (to centralize the version number)</li>
<li>Reading the long_description content from a text-file</li>
</ul>
<p>Both methodologies have their issues. Importing the package only works if you <em>can</em> import it cleanly (i.e. without dependencies) from standard python. Reading the text file only works if the <tt>setup.py</tt> is called from the proper location.</p>
<p>This is <em>mostly</em> true. There are corner-cases however where this is not possible. If that is the case, you will need to live without these helpful shortcuts. See the comments on this article for more on this.
</div>
<p><span id="more-270"></span></p>
<h2>Our Hello World project</h2>
<p>Our project will provide the following:</p>
<ul>
<li>a package called <tt>helloworld</tt></li>
<li>a method returning the string &#8220;Hello World!&#8221;</li>
<li>an executable printing &#8220;Hello World!&#8221; to the standard output.</li>
</ul>
<h2>Creating a package distribution</h2>
<p>Before you can do any of the aforementioned points, you need to be able to create a package file. In most cases, this would be a tarball (a source distribution). First, you need to think about your file layout:</p>
<p>In python, every package lives in its own folder. Unless you have a one-file module. For the sake of this post, I will assume you have a folder, and leave the one-file module as an exercise to the reader. After all, the differences are not all that great. Let&#8217;s also assume, for the sake of simplicity, we have only one module in our package folder.</p>
<h2>Let&#8217;s create the package</h2>
<p>First, the file laout:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">the-helloworld-project<br />
└── helloworld<br />
&nbsp; &nbsp; ├── __init__.py<br />
&nbsp; &nbsp; └── core.py</div></div>
<p class="admonition note"><strong>NOTE:</strong> This is just an <em>example</em> project, and it could have been implemented as a one-file module (using <tt>core.py</tt>), or the application logic could have been stuffed into <tt>__int__.py</tt>. But I assume that multi-file packages are far more common, so I will use an appropriate layout for that. Also, I personally like to <em>always </em>create my projects like this. On the one hand for consistency, and on the other hand it makes it easier to &#8220;grow&#8221; the project later on. It&#8217;s up to you to decide for yourself.</p>
<p>In this case, I named the project root &#8220;the-helloworld-project&#8221;. But (again, personally), I just give the root folder the same name as the package name. The difference between the root (&#8220;the-helloworld-project&#8221;) and the package (&#8220;helloworld&#8221;) is that  the package folder contains the actual package code, and the root folder contains packaging metadata and possibly some other development related stuff (unit-tests, fabric files, a readme, the license file, &#8230;)</p>
<p>Next, let&#8217;s create our business logic. For our target features, we need both a method generating our &#8220;Hello World!&#8221; message, and one to print it to stdout. Let&#8217;s put this into <tt>helloworld/core.py</tt>:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> get_message<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;Hello World!&quot;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> print_message<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> get_message<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<p>So far so good. We have our business logic. Yay \o/.</p>
<h2>Creating a skeleton setup.py file</h2>
<p>Next up, we will create a <em>very</em> simple <tt>setup.py</tt> file. Let&#8217;s also add a <tt>README.txt</tt> file for good measure (it should be formatted in <a href="http://docutils.sourceforge.net/rst.html">ReST</a>!):</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Description<br />
===========<br />
<br />
An example Hello World project.</div></div>
<p>Next, let&#8217;s create a very simple setup script, and put it into the root folder:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup<span style="color: #66cc66;">,</span> find_packages<br />
<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'helloworld'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; version<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'1.0'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; packages<span style="color: #66cc66;">=</span>find_packages<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; long_description<span style="color: #66cc66;">=</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'README.txt'</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
<span style="color: black;">&#41;</span></div></div>
<p>Note that we don&#8217;t use <tt>distutils</tt>, but <tt>setuptools</tt>. You will be better off with <tt>setuptools</tt> until <tt>distutils2</tt> is available.</p>
<p class="admonition warning"><strong>IMPORTANT:</strong><br />
The package <tt>setuptools</tt> is actually made available by a package named <tt>distribute</tt>. You should <em>not</em> install the old <tt>setuptools</tt> any more!
</p>
<h3>WARNING</h3>
<p>As Ionel Maries Cristian pointed out in the comments, the line <tt>long_description=open('README.txt').read()</tt> could cause problems. Let&#8217;s make it safer&#8230;</p>
<p>We know that the README file sits in the same folder as the setup script. So we can use <tt>os.path.dirname</tt> on <tt>__file__</tt> to construct a filename we can reach:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup<span style="color: #66cc66;">,</span> find_packages<br />
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span> <span style="color: #ff7700;font-weight:bold;">import</span> join<span style="color: #66cc66;">,</span> dirname<br />
<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'helloworld'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; version<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'1.0'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; packages<span style="color: #66cc66;">=</span>find_packages<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; long_description<span style="color: #66cc66;">=</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span>join<span style="color: black;">&#40;</span>dirname<span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'README.txt'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
<span style="color: black;">&#41;</span></div></div>
<p>Now we can test to create a source distribution by running:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">python setup.py sdist</div></div>
<p>There will be some warnings as we did fill in neither an author email nor a package URL. For this example we consider this okay!</p>
<p>This will give you a file called <tt>sdist/helloworld-1.0.tar.gz</tt>. You can inspect it if you want using <tt>tar tzvf sdist/helloworld-1.0.tar.gz</tt>.</p>
<p>With this done, we already have two points of our targets done:</p>
<ul>
<li><del datetime="2012-05-13T09:50:57+00:00">a package called <tt>helloworld</tt></del></li>
<li><del datetime="2012-05-13T09:50:57+00:00">a method returning the string &#8220;Hello World!&#8221;</del></li>
<li>an executable printing &#8220;Hello World!&#8221; to the standard output.</li>
</ul>
<h2>Testing inside a virtual environment</h2>
<p>The details about virtual environments are out of the scope of this document (see <a href="http://pypi.python.org/pypi/virtualenv/">the package documentation</a> for more). But because it is <em>highly</em> recommended to use them, we will do so right now. This gives us the ability to test the package installation without polluting our system packages.</p>
<p>So let&#8217;s create one:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">virtualenv env</div></div>
<p>This will create an environment called <tt>env</tt> in our current working folder and install <tt>pip</tt> and <tt>distribute</tt> into it. With this in place, we can already test the package installation:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./env/bin/python setup.py install<br />
running install<br />
running bdist_egg<br />
running egg_info<br />
[...]<br />
Processing dependencies for helloworld==1.0<br />
Finished processing dependencies for helloworld==1.0</div></div>
<p>Now we can test our package within the virtual environment:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./env/bin/python<br />
&gt;&gt;&gt; import helloworld.core as hw<br />
&gt;&gt;&gt; hw.get_message()<br />
'Hello World!'<br />
&gt;&gt;&gt; hw.print_message()<br />
Hello World!</div></div>
<p>Perfekt!</p>
<p>But we still want our executable&#8230;</p>
<h2>Creating an executable</h2>
<p>Following <a href="http://docs.python.org/distutils/setupscript.html#installing-scripts">the official <tt>distutils</tt> documentation</a>, we should specify the <tt>scripts</tt> keyword argument on the <tt>setup</tt> method. On the other hand, <tt>distribute</tt> gives us <a href="http://guide.python-distribute.org/creation.html#entry-points">entry points</a>. Personally, I prefer entry points. So let&#8217;s get this done. Modify the <tt>setup.py</tt> file and add the following:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: black;">entry_points</span><span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'console_scripts'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#91;</span><span style="color: #483d8b;">'helloworld = helloworld.core:print_message'</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: black;">&#41;</span></div></div>
<p>The complete setup.py file should now look like this:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup<span style="color: #66cc66;">,</span> find_packages<br />
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span> <span style="color: #ff7700;font-weight:bold;">import</span> join<span style="color: #66cc66;">,</span> dirname<br />
<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'helloworld'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; version<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'1.0'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; packages<span style="color: #66cc66;">=</span>find_packages<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; long_description<span style="color: #66cc66;">=</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span>join<span style="color: black;">&#40;</span>dirname<span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'README.txt'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; entry_points<span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'console_scripts'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#91;</span><span style="color: #483d8b;">'helloworld = helloworld.core:print_message'</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: black;">&#41;</span></div></div>
<p>What does this mean?</p>
<ul>
<li><tt>helloworld = ...</tt><br />
        Create an executable with the name <tt>helloworld</tt> (on windows it will be a .exe file)</li>
<li><tt>... = helloworld.core:...</tt><br />
        The method is found in this package</li>
<li><tt>... :print_message</tt><br />
        Call this method on execution</li>
</ul>
<p>Let&#8217;s re-install our package:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./env/bin/python setup.py install<br />
...<br />
Installing helloworld script to /path/to/the-helloworld-project/env/bin<br />
...<br />
$</div></div>
<p>As you can see in the output, the setup script installed an executable into our local <tt>bin</tt> folder. If you execute it, your method from your package will be executed.</p>
<p>Awesome!  We can cross the last item off our basic tasks:</p>
<ul>
<li><del datetime="2012-05-13T09:50:57+00:00">a package called <tt>helloworld</tt></del></li>
<li><del datetime="2012-05-13T09:50:57+00:00">a method returning the string &#8220;Hello World!&#8221;</del></li>
<li><del datetime="2012-05-13T09:50:57+00:00">an executable printing &#8220;Hello World!&#8221; to the standard output.</del></li>
</ul>
<div class="admonition note">
When running the setup script, you can also use the <tt>develop</tt> command instead of the <tt>install</tt> command. This will link the installed package with your source files. In this way, you don&#8217;t need to re-install the package when you change the source code. However, when you change something in your <tt>setup.py</tt> file, you need to re-run it of course!</p>
<p>Additionally, with <tt>pip</tt> you can instead use <tt>pip install -e .</tt> to achieve the same as with <tt>python setup.py develop</tt> with the advantage that <tt>pip</tt> also has an <tt>uninstall</tt> command.
</div>
<h2>Version Numbers</h2>
<p>Version numbers are a very important part of your project! You should manage them as soon as possible. They are primarily important in two situation:</p>
<ul>
<li>Installation of the package if an older version exists already (upgrading)</li>
<li>Dependency management</li>
</ul>
<p class="warning admonition">
If you ever publish a package, it should always stay available! People using your package have the option to &#8220;pin&#8221; a version in their dependencies. Because of this, you will never know how long a specific version is going to be used. Again: Once published it should <em><strong>never</strong></em> disappear!
</p>
<p>In the above example, we &#8220;hard-coded&#8221; the version number as <tt>1.0</tt>. There is a better solution however! It would be nice to give your package users the ability to check the version number. To do that, we will move the version number into our top-level <tt>__init__.py</tt> file. By convention, the variable should be named <tt>__version__</tt>. In our package, this will be the only line in the file:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">__version__ = '1.0'</div></div>
<p>This will allow users to do the following:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&gt;&gt;&gt; import helloworld<br />
&gt;&gt;&gt; print helloworld.__version__<br />
'1.0'</div></div>
<p>This is a <em>very</em> convenient information to have!</p>
<p>But now there is one annoyance&#8230; We have to edit the version number in two locations. In our setup script, and the </tt>__init__.py</tt> file. But there's a simple solution for that. In your setup script, simply import your project and get the version number from there.</p>
<p class="warning admonition">
<strong>WARNING:</strong><br />
As <a href="http://www.reddit.com/r/Python/comments/tkwtt/a_comprehensive_guide_through_python_packaging/c4nljj6">bboe over on reddit pointed out</a>, when doing this, you must be aware that this could fail if the project tries to import one of it's dependencies when importing <tt>helloworld</tt>. As the dependency cannot be available yet when running the script, it will raise an <tt>ImportError</tt>. So, either you don't import the version variable, or you must not trigger an import of any dependency when importing the package.<br />&nbsp;<br />Other alternatives are possible. Such as storing your version number in a separate <tt>.py</tt> file and importing that one. Or, if all else fails, running a regex on you <tt>__init__.py</tt> file. You can see implementations of these solutions in the <a href="http://www.reddit.com/r/Python/comments/tkwtt/a_comprehensive_guide_through_python_packaging/c4nljj6">reddit link</a> mentioned before.
</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> helloworld<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: black;">version</span><span style="color: #66cc66;">=</span>helloworld.__version__<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; ...</div></div>
<p>which will give you this result:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup<span style="color: #66cc66;">,</span> find_packages<br />
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span> <span style="color: #ff7700;font-weight:bold;">import</span> join<span style="color: #66cc66;">,</span> dirname<br />
<span style="color: #ff7700;font-weight:bold;">import</span> helloworld<br />
<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'helloworld'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; version<span style="color: #66cc66;">=</span>helloworld.__version__<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; packages<span style="color: #66cc66;">=</span>find_packages<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; long_description<span style="color: #66cc66;">=</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span>join<span style="color: black;">&#40;</span>dirname<span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'README.txt'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; entry_points<span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'console_scripts'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#91;</span><span style="color: #483d8b;">'helloworld = helloworld.core:print_message'</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#125;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: black;">&#41;</span></div></div>
<p>It is recommended that the version numbers follow a well-known scheme. There are a few:</p>
<ul>
<li><a href="http://www.python.org/dev/peps/pep-0386/">from PEP 386</a></li>
<li><a href="http://docs.python.org/distutils/setupscript.html#additional-meta-data">from The official documentation</a></li>
<li><a href="http://guide.python-distribute.org/specification.html#how-to-version-your-python-projects">from The Hitchhiker's Guide</a></li>
</ul>
<p>I suggest following the "strict" numbers stated in PEP386 for <tt>distutils</tt>. An example from the PEP document (ordered by version number):</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; 0.4 &nbsp; &nbsp; &nbsp; 0.4.0 &nbsp;(these two are equivalent)<br />
&nbsp; &nbsp; 0.4.1<br />
&nbsp; &nbsp; 0.5a1<br />
&nbsp; &nbsp; 0.5b3<br />
&nbsp; &nbsp; 0.5<br />
&nbsp; &nbsp; 0.9.6<br />
&nbsp; &nbsp; 1.0<br />
&nbsp; &nbsp; 1.0.4a3<br />
&nbsp; &nbsp; 1.0.4b1<br />
&nbsp; &nbsp; 1.0.4</div></div>
<h2>Dependency Management</h2>
<p>As stated above, with setup scripts, you can specify dependencies. So let's make a small hello-world web application using Flask. A web-app will also contain "data" files (templates, ...), which will give us the opportunity to talk about the manifest later on. But for now, let's simply add <tt>Flask</tt> into our dependencies. To do that, add the following to your setup script:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: black;">install_requires</span><span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'Flask'</span><br />
&nbsp; &nbsp; <span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; ...</div></div>
<p>So the complete setup script now reads:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup<span style="color: #66cc66;">,</span> find_packages<br />
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span> <span style="color: #ff7700;font-weight:bold;">import</span> join<span style="color: #66cc66;">,</span> dirname<br />
<span style="color: #ff7700;font-weight:bold;">import</span> helloworld<br />
<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'helloworld'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; version<span style="color: #66cc66;">=</span>helloworld.__version__<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; packages<span style="color: #66cc66;">=</span>find_packages<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; long_description<span style="color: #66cc66;">=</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span>join<span style="color: black;">&#40;</span>dirname<span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'README.txt'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; entry_points<span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'console_scripts'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#91;</span><span style="color: #483d8b;">'helloworld = helloworld.core:print_message'</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#125;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; install_requires<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'Flask'</span><br />
&nbsp; &nbsp; <span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: black;">&#41;</span></div></div>
<p>Let's run the script again. But let's use <tt>pip</tt> now:<tt>./env/bin/pip install -e .</tt>. Alternatively we could have used <tt>./env/bin/python setup.py install</tt> or <tt>./env/bin/python setup.py develop</tt>, but <tt>pip</tt> gives us the option of uninstalling. Not that this would matter in our development environment. But it's good to know it exists. On the output, we will see that this will now automagically pull in everything required. Python will automatically query <a href="http://pypi.python.org/pypi">pypi</a> to find the latest version of <tt>Flask</tt> and follow it's dependencies.</p>
<p>Okay. So now we got the latest <tt>Flask</tt> version, and we will start to develop against that version. Because of this, we want to pin the version, so that we (and our users) will not be surprised if the API of Flask will change in the future. To determine the version of Flask, we can run the following:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./env/bin/pip freeze<br />
...<br />
Flask==0.8<br />
...</div></div>
<p>This will list all packages, including the version number installed in the environment from which <tt>pip</tt> was run.</p>
<p class="note admonition">
This output can also be used as a "requirements file" for <tt>pip</tt> installations. I won't cover that topic yet. It's still new to me <img src='http://foobar.lu/wp/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />
</p>
<p>So now we know we got version 0.8. We can now change our setup script to pin our version:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: black;">install_requires</span><span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'Flask==0.8'</span><br />
&nbsp; &nbsp; <span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; ...</div></div>
<p>You are strongly encouraged to do this as it puts <em>you</em> in control about when and where you will upgrade to newer versions!</p>
<p>Now, as a small interlude, let's create a one-page web application, basing ourselves on the integrated server. This will also give us the opportunity to revisit the creation of executables. In a production environment, you should not do this, but rather deploy a WSGI application. But this post is not about web application. We just want some "data" files!</p>
<p>Create a folder for our templates (which incidentally contains our only data file):</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ mkdir helloworld/templates</div></div>
<p>... and put the following file into it, called <tt>index.html</tt>:</p>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #00bbdd;">&lt;!DOCTYPE HTML&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span> <span style="color: #000066;">lang</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;en&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;UTF-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; {{message}}<br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
<p>Next, create the Flask entry point inside <tt>helloworld/web.py</tt></p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> flask <span style="color: #ff7700;font-weight:bold;">import</span> Flask<span style="color: #66cc66;">,</span> render_template<br />
<span style="color: #ff7700;font-weight:bold;">from</span> helloworld.<span style="color: black;">core</span> <span style="color: #ff7700;font-weight:bold;">import</span> get_message<br />
app <span style="color: #66cc66;">=</span> Flask<span style="color: black;">&#40;</span>__name__<span style="color: black;">&#41;</span><br />
<br />
<br />
<span style="color: #66cc66;">@</span>app.<span style="color: black;">route</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;/&quot;</span><span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">def</span> hello<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> render_template<span style="color: black;">&#40;</span><span style="color: #483d8b;">'index.html'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; message<span style="color: #66cc66;">=</span>get_message<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> run_server<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; app.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<p>... and add the entry-point to setup.py:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup<span style="color: #66cc66;">,</span> find_packages<br />
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span> <span style="color: #ff7700;font-weight:bold;">import</span> join<span style="color: #66cc66;">,</span> dirname<br />
<span style="color: #ff7700;font-weight:bold;">import</span> helloworld<br />
<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'helloworld'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; version<span style="color: #66cc66;">=</span>helloworld.__version__<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; packages<span style="color: #66cc66;">=</span>find_packages<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; long_description<span style="color: #66cc66;">=</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span>join<span style="color: black;">&#40;</span>dirname<span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'README.txt'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; entry_points<span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'console_scripts'</span>: <span style="color: black;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'helloworld = helloworld.core:print_message'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'serve = helloworld.web:run_server'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#125;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; install_requires<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'Flask==0.8'</span><br />
&nbsp; &nbsp; <span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: black;">&#41;</span></div></div>
<p>Execute the setup script again (to make the new executable available):</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./env/bin/python setup.py develop</div></div>
<p>... and test the server:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./env/bin/serve<br />
&nbsp;* Running on http://127.0.0.1:5000/</div></div>
<p>Good! We have everything in place to talk about the manifest.</p>
<h2>The MANIFEST</h2>
<p>There is still one problem with our project. By default the package only contains python files. If you need to add additional data, for example template of image files in a web-application, you need to specify these. The above example contains a template. So let's see what this means for us. Let's create a new source distribution:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ python setup.py sdist</div></div>
<p>Now, inspect the contents of the tarball:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ tar tzvf dist/helloworld-1.0.tar.gz<br />
drwxrwxr-x exhuma/exhuma &nbsp; &nbsp; 0 2012-05-13 15:02 helloworld-1.0/<br />
-rw-rw-r-- exhuma/exhuma &nbsp; 443 2012-05-13 14:55 helloworld-1.0/setup.py<br />
drwxrwxr-x exhuma/exhuma &nbsp; &nbsp; 0 2012-05-13 15:02 helloworld-1.0/helloworld/<br />
-rw-rw-r-- exhuma/exhuma &nbsp; &nbsp;91 2012-05-13 12:46 helloworld-1.0/helloworld/core.py<br />
-rw-rw-r-- exhuma/exhuma &nbsp; 249 2012-05-13 14:57 helloworld-1.0/helloworld/web.py<br />
-rw-rw-r-- exhuma/exhuma &nbsp; &nbsp;20 2012-05-13 14:34 helloworld-1.0/helloworld/__init__.py<br />
-rw-rw-r-- exhuma/exhuma &nbsp; 264 2012-05-13 15:02 helloworld-1.0/PKG-INFO<br />
drwxrwxr-x exhuma/exhuma &nbsp; &nbsp; 0 2012-05-13 15:02 helloworld-1.0/helloworld.egg-info/<br />
-rw-rw-r-- exhuma/exhuma &nbsp; &nbsp;10 2012-05-13 15:02 helloworld-1.0/helloworld.egg-info/requires.txt<br />
-rw-rw-r-- exhuma/exhuma &nbsp; 264 2012-05-13 15:02 helloworld-1.0/helloworld.egg-info/PKG-INFO<br />
-rw-rw-r-- exhuma/exhuma &nbsp; &nbsp;96 2012-05-13 15:02 helloworld-1.0/helloworld.egg-info/entry_points.txt<br />
-rw-rw-r-- exhuma/exhuma &nbsp; &nbsp;11 2012-05-13 15:02 helloworld-1.0/helloworld.egg-info/top_level.txt<br />
-rw-rw-r-- exhuma/exhuma &nbsp; &nbsp; 1 2012-05-13 15:02 helloworld-1.0/helloworld.egg-info/dependency_links.txt<br />
-rw-rw-r-- exhuma/exhuma &nbsp; 285 2012-05-13 15:02 helloworld-1.0/helloworld.egg-info/SOURCES.txt<br />
-rw-rw-r-- exhuma/exhuma &nbsp; &nbsp;59 2012-05-13 15:02 helloworld-1.0/setup.cfg<br />
-rw-rw-r-- exhuma/exhuma &nbsp; &nbsp;57 2012-05-13 12:50 helloworld-1.0/README.txt</div></div>
<p>As you can see, the templates are not included! So our package <strong>will not work</strong> if we distribute like this! To do this, we need to tell python that we want other non-source files to be added. We can do this easily with a file called <tt>MANIFEST.in</tt>. In our case, it will look like this:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">recursive-include helloworld/templates *.html</div></div>
<p>Finally, we need to add the following line to the setup script:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: black;">include_package_data</span><span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: black;">&#41;</span></div></div>
<p>There are other ways to address the issue of data files. Most notably, as of Python 2.7, the setup procedure will automatically create a manifest based on <tt>package_data</tt> and <tt>data_files</tt>. The advantage of this is that your setup specs are no longer split into multiple files. As it is fairly new, and as Python 2.7 is only now gaining traction, I have not yet worked with this. I leave this as an exercise to the reader.</p>
<p>If we now re-create the sdist, we see that the files are included in the tarball. We need to do this for all non-source files which we want to include in our project! You can find more detailed information on <a href="http://docs.python.org/distutils/sourcedist.html#specifying-the-files-to-distribute">this in the official documentation</a>.</p>
<h3>Accessing packaged files</h3>
<p>When you need to access these packaged data files you cannot simply use <tt>open(filename)</tt>. You don't know the filename! It could even be stored inside a <tt>.egg</tt>. This all depends on how the end-user will install the package. You don't have control over this! For this reason, <tt>distribute</tt> provides <a href="http://packages.python.org/distribute/pkg_resources.html#basic-resource-access">a couple of methods</a> to access these files. The most likely candidates are:</p>
<ul>
<li><tt>resource_stream</tt> which returns a file-like object,</li>
<li><tt>resource_string</tt> which returns a string and</li>
<li><tt>resource_filename</tt></li>
</ul>
<p>Note that when using <tt>resource_filename</tt> the resource may be (in the case of a zipped installation) extracted to a cache folder. See the <a href="http://packages.python.org/distribute/pkg_resources.html#resource-extraction">pkg_resources (resource-extraction)</a> for details on this behaviour.</p>
<h2>Publishing</h2>
<p>If you want to make your package available to others, the obvious choice is <a href="http://pypi.python.org/pypi">pypi</a>. Python makes it easy to publish. Simply run:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ python setup.py register sdist upload</div></div>
<p>See <a href="http://guide.python-distribute.org/contributing.html#registering-projects">the hitchhiker's guide</a> for more details on this.</p>
<p>Before you publish on <tt>pypi</tt> you may want to test your upload process. For this reason, there is http://testpypi.python.org/pypi<br />
To use this (or any other package index), you need to specify the details in your <tt>~/.pypirc</tt>. Here is an example:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[distutils]<br />
index-servers =<br />
&nbsp; &nbsp; pypi<br />
&nbsp; &nbsp; ppt<br />
<br />
[pypi]<br />
username:yourlogin<br />
password:yourpasswd<br />
<br />
[ppt]<br />
repository: http://testpypi.python.org/pypi<br />
username:test<br />
password:test</div></div>
<p>Having this, you can then upload packages to the given repositories by appending <tt>-r ppt</tt> for example.</p>
<div class="admonition warning">
I was testing this while I was writing this and it triggered an infinite recursion. Following the comment of Richard Jones it should work. Maybe someone can shed some light on this?
</div>
<p>But corporate policy may prevent you from publishing to the public domain. Or your project contains sensitive data which should not be made public. In this case, it is very easy to set up a local repository of packages. You only need to have a HTML document with the links available. A very easy way is to set up an Apache host which indexes a folder into which you upload your packages.</p>
<p>Even if not behind corporate restrictions, this is an easy way to publish pre-release packages which you don't want to push to pypi just yet.</p>
<p>To be able to use these repositories for your dependencies, you need to add the links into your setup.py file. Let's assume you create a new package depending on our <tt>helloworld</tt> package which we published on our local repository, and that your local repository is available as http://our.local.repo/. Then you would create a setup script like this:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup<span style="color: #66cc66;">,</span> find_packages<br />
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span> <span style="color: #ff7700;font-weight:bold;">import</span> join<span style="color: #66cc66;">,</span> dirname<br />
<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'myotherproject'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; version<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'1.0'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; packages<span style="color: #66cc66;">=</span>find_packages<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; long_description<span style="color: #66cc66;">=</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span>join<span style="color: black;">&#40;</span>dirname<span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'README.txt'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; install_requires<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'helloworld==1.0'</span><br />
&nbsp; &nbsp; <span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; dependency_links <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'http://our.local.repo'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></div></div>
<p>Alternatively, when using <tt>pip</tt>, you can specify URLs at which to look for packages using <tt>pip -f ...</tt>.</p>
<h2>Food for thought</h2>
<p>As promised, here's another tidbit. For many python beginners, the <tt>setup.py</tt> file is some sort of black magic and must contain the call to the <tt>setup</tt> method and nothing else. But that is <strong>not</strong> true! The setup script is a completely normal python file which you execute. This has an <em>awesome</em> implication: You can do <em>whatever you want</em> before and after the call to <tt>setup</tt>. Everything you execute before the call to setup, will obviously be run before the setup process, everything after the setup call will in turn be run after the installation is finished. I will let your imagination run wild with what you can do. Keep in mind though, that you may want to keep away from user-prompts and so forth to avoid breaking automated installations! But it is your project and your choice what you will or won't do.</p>
<p>In most cases this level of fine-tuning is not needed however <tt>distribute</tt> and <tt>distutils</tt> already offer a <em>lot</em> of functionality. Investigate these first! Only do such things if there is really no other way around! Or if you want to play around <img src='http://foobar.lu/wp/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2>References</h2>
<ul>
<li><a href="http://guide.python-distribute.org/">The Hitchhiker's Guide to Python Packaging</a></li>
<li><a href="http://www.ibm.com/developerworks/opensource/library/os-pythonpackaging/">A Guide to Python Packagin (IBM)</a></li>
<li>The official Python documentation (<a href="http://docs.python.org/distutils/setupscript.html">setupscript</a>, <a href="http://docs.python.org/distutils/sourcedist.html">source-dist</a>)</li>
<li><a href="http://packages.python.org/distribute">Distribute</a></li>
<li><a href="http://www.python.org/dev/peps/pep-0386/">PEP 386 - Changing the version comparison module in Distutils</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2012/05/13/a-comprehensive-step-through-python-packaging-a-k-a-setup-scripts/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Unable to easy_install psycopg2 on debian</title>
		<link>http://foobar.lu/wp/2009/10/29/unable-to-easy_install-psycopg2-on-debian/</link>
		<comments>http://foobar.lu/wp/2009/10/29/unable-to-easy_install-psycopg2-on-debian/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 15:18:30 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/?p=66</guid>
		<description><![CDATA[Problem: $ easy_install psycopg2 Searching for psycopg2 &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<h3>Problem:</h3>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ easy_install psycopg2<br />
Searching for psycopg2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
Reading http://pypi.python.org/simple/psycopg2/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
Reading http://initd.org/projects/psycopg2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
Reading http://initd.org/pub/software/psycopg/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
Best match: psycopg2 2.0.13 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
Downloading http://initd.org/pub/software/psycopg/psycopg2-2.0.13.tar.gz &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
Processing psycopg2-2.0.13.tar.gz &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
Running psycopg2-2.0.13/setup.py -q bdist_egg --dist-dir /tmp/easy_install-cHE0C_/psycopg2-2.0.13/egg-dist-tmp-x-CxRS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
error: Setup script exited with error: No such file or directory</div></div>
<h3>Solution:</h3>
<p>This most likely indicates that you are missing the &#8220;libpq&#8221; headers:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo aptitude install libpq-dev</div></div>
<p>should solve the problem</p>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2009/10/29/unable-to-easy_install-psycopg2-on-debian/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python startup (command completion &amp; history)</title>
		<link>http://foobar.lu/wp/2008/08/21/python-startup-command-completion-history/</link>
		<comments>http://foobar.lu/wp/2008/08/21/python-startup-command-completion-history/#comments</comments>
		<pubDate>Thu, 21 Aug 2008 11:18:17 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/2008/08/21/python-startup-command-completion-history/</guid>
		<description><![CDATA[If you want command completion and a history in your python shell, export the PYTHONSTARTUP env var (export PYTHONSTARTUP=$HOME/.pystartup) in your bashrc and create a file ~/.pystartup with the following contents: import atexit import os import readline import rlcompleter historyPath = os.path.expanduser&#40;&#34;~/.pyhistory&#34;&#41; def save_history&#40;historyPath=historyPath&#41;: import readline readline.write_history_file&#40;historyPath&#41; if os.path.exists&#40;historyPath&#41;: readline.read_history_file&#40;historyPath&#41; readline.parse_and_bind&#40;'tab: complete'&#41; atexit.register&#40;save_history&#41; del os, [...]]]></description>
			<content:encoded><![CDATA[<p>If you want command completion and a history in your python shell, export the <em>PYTHONSTARTUP</em> env var (<em>export PYTHONSTARTUP=$HOME/.pystartup) </em>in your bashrc and create a file ~/.pystartup with the following contents:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">atexit</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">readline</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">rlcompleter</span><br />
<br />
historyPath <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">expanduser</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;~/.pyhistory&quot;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> save_history<span style="color: black;">&#40;</span>historyPath<span style="color: #66cc66;">=</span>historyPath<span style="color: black;">&#41;</span>:<br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">readline</span><br />
<span style="color: #dc143c;">readline</span>.<span style="color: black;">write_history_file</span><span style="color: black;">&#40;</span>historyPath<span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span>historyPath<span style="color: black;">&#41;</span>:<br />
<span style="color: #dc143c;">readline</span>.<span style="color: black;">read_history_file</span><span style="color: black;">&#40;</span>historyPath<span style="color: black;">&#41;</span><br />
<br />
<span style="color: #dc143c;">readline</span>.<span style="color: black;">parse_and_bind</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'tab: complete'</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #dc143c;">atexit</span>.<span style="color: black;">register</span><span style="color: black;">&#40;</span>save_history<span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">del</span> <span style="color: #dc143c;">os</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">atexit</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">readline</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">rlcompleter</span><span style="color: #66cc66;">,</span> save_history<span style="color: #66cc66;">,</span> historyPath</div></div>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2008/08/21/python-startup-command-completion-history/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vim script (mapping) to generate python getters and setters</title>
		<link>http://foobar.lu/wp/2007/12/31/vim-script-mapping-to-generate-python-getters-and-setters/</link>
		<comments>http://foobar.lu/wp/2007/12/31/vim-script-mapping-to-generate-python-getters-and-setters/#comments</comments>
		<pubDate>Mon, 31 Dec 2007 09:59:46 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/2007/12/31/vim-script-mapping-to-generate-python-getters-and-setters/</guid>
		<description><![CDATA[Somethin that I need quite often is to create custom accessors and mutators for class-attributes. For example convert this: class MyClass&#40;object&#41;: &#160; &#160; &#160; &#160;def __init__&#40;self&#41;: &#160; &#160; &#160; self.has_changes = False &#160; &#160; &#160; self.some_attribute = False into this: class MyClass&#40;object&#41;: &#160; &#160; &#160; &#160;def __init__&#40;self&#41;: &#160; &#160; &#160; self.__has_changes = False &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>Somethin that I need quite often is to create custom accessors and mutators for class-attributes. For example convert this:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> MyClass<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">has_changes</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">some_attribute</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span></div></div>
<p>into this:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> MyClass<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.__has_changes <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.__some_attribute <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span><br />
<br />
&nbsp; &nbsp;<span style="color: #ff7700;font-weight:bold;">def</span> get_some_attribute<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">&quot;Accessor: some_attribute&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.__some_attribute<br />
<br />
&nbsp; &nbsp;<span style="color: #ff7700;font-weight:bold;">def</span> set_some_attribute<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">input</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">&quot;Mutator: some_attribute&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.__some_attribute <span style="color: #66cc66;">=</span> <span style="color: #008000;">input</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.__has_changes <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span><br />
<br />
&nbsp; &nbsp;some_attribute <span style="color: #66cc66;">=</span> <span style="color: #008000;">property</span><span style="color: black;">&#40;</span>get_some_attribute<span style="color: #66cc66;">,</span> set_some_attribute<span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #ff7700;font-weight:bold;">def</span> get_has_changes<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">&quot;Accessor: has_changes&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.__has_changes<br />
<br />
&nbsp; &nbsp;has_changes <span style="color: #66cc66;">=</span> <span style="color: #008000;">property</span><span style="color: black;">&#40;</span>get_has_changes<span style="color: black;">&#41;</span></div></div>
<p>This particular example allows an easy tracking if a class contains changes. Without the need of calling <tt>myclass.get_some_attribute()</tt> or <tt>myclass.set_some_attribute(foo)</tt>. You can simply do <tt>myclass.some_attribute = foo</tt> and the <tt>has_changes</tt> attribut will change accordingly.</p>
<p>If your class has many attributes, writing custom accessors and mutators can be tedious. So here&#8217;s a small Vim-mapping that get&#8217;s you started. Sure, you may still need to fine-tune some generated code, but the bulk is there.</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;font color=&quot;#808bed&quot;&gt;nmap&lt;/font&gt; &lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;F6&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt; yyP&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;home&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;widef get_&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;end&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;(self):&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;down&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;yyP&amp;gt;&amp;gt;I&amp;quot;Accessor: &lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;end&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;&amp;quot;&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;down&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;yyP&amp;gt;&amp;gt;Ireturn self.__&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;o&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;down&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;yyPIdef set_&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;end&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;(self, input):&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;down&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;yyP&amp;gt;&amp;gt;I&amp;quot;Mutator: &lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;end&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;&amp;quot;&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;down&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;yyP&amp;gt;&amp;gt;Iself.__&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;end&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt; = input&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;o&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;down&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;home&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;wveyA = property(get_&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;pA, set_&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;pA)&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;o&lt;font color=&quot;#c080d0&quot;&gt;&amp;lt;&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;esc&lt;/font&gt;&lt;font color=&quot;#c080d0&quot;&gt;&amp;gt;&lt;/font&gt;</div></div>
<p>Put this into your vimrc, or (like I do) into the ~/.vim/ftplugin/python.vim file so it get&#8217;s only loaded for python files. Then you only need to write the attribute name of the class, put your cursor on that line, be sure to be in normal mode (hit a few time &lt;esc&gt;) <img src='http://foobar.lu/wp/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  and hit F6</p>
<p>If you want to change the shortcut, simply change the first parameter to this mapping line.</p>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2007/12/31/vim-script-mapping-to-generate-python-getters-and-setters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calculate the distance between two GPS-Coordinates</title>
		<link>http://foobar.lu/wp/2007/09/17/calculate-the-distance-between-two-gps-coordinates/</link>
		<comments>http://foobar.lu/wp/2007/09/17/calculate-the-distance-between-two-gps-coordinates/#comments</comments>
		<pubDate>Mon, 17 Sep 2007 08:58:17 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/2007/09/17/calculate-the-distance-between-two-gps-coordinates/</guid>
		<description><![CDATA[This function uses the Haversine formula to calculate the distance which takes into account the spherical nature of the earth. As the earth is not a perfect sphere, this function approximates this by using the average radius. from math import sin, cos, radians, sqrt, asin def lldistance&#40;a, b&#41;: &#160; &#160;&#34;&#34;&#34; &#160; &#160;Calculates the distance between [...]]]></description>
			<content:encoded><![CDATA[<p>This function uses the Haversine formula to calculate the distance which takes into account the spherical nature of the earth.<br />
As the earth is not a perfect sphere, this function approximates this by using the average radius.</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">math</span> <span style="color: #ff7700;font-weight:bold;">import</span> sin<span style="color: #66cc66;">,</span> cos<span style="color: #66cc66;">,</span> radians<span style="color: #66cc66;">,</span> sqrt<span style="color: #66cc66;">,</span> asin<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> lldistance<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp;<span style="color: #483d8b;">&quot;&quot;&quot;<br />
&nbsp; &nbsp;Calculates the distance between two GPS points (decimal)<br />
&nbsp; &nbsp;@param a: 2-tuple of point A<br />
&nbsp; &nbsp;@param b: 2-tuple of point B<br />
&nbsp; &nbsp;@return: distance in m<br />
&nbsp; &nbsp;&quot;&quot;&quot;</span><br />
&nbsp; &nbsp;r <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">6367442.5</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># average earth radius in m</span><br />
&nbsp; &nbsp;dLat <span style="color: #66cc66;">=</span> radians<span style="color: black;">&#40;</span>a<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>-b<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;dLon <span style="color: #66cc66;">=</span> radians<span style="color: black;">&#40;</span>a<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>-b<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;x <span style="color: #66cc66;">=</span> sin<span style="color: black;">&#40;</span>dLat/<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> ** <span style="color: #ff4500;">2</span> + \<br />
&nbsp; &nbsp; &nbsp; &nbsp;cos<span style="color: black;">&#40;</span>radians<span style="color: black;">&#40;</span>a<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> * cos<span style="color: black;">&#40;</span>radians<span style="color: black;">&#40;</span>b<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> *\<br />
&nbsp; &nbsp; &nbsp; &nbsp;sin<span style="color: black;">&#40;</span>dLon/<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> ** <span style="color: #ff4500;">2</span><br />
&nbsp; &nbsp;y <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">2</span> * asin<span style="color: black;">&#40;</span>sqrt<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;d <span style="color: #66cc66;">=</span> r * y<br />
<br />
&nbsp; &nbsp;<span style="color: #ff7700;font-weight:bold;">return</span> d</div></div>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2007/09/17/calculate-the-distance-between-two-gps-coordinates/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Centering a window on the screen with Qt</title>
		<link>http://foobar.lu/wp/2007/09/10/centering-a-window-on-the-screen-with-qt/</link>
		<comments>http://foobar.lu/wp/2007/09/10/centering-a-window-on-the-screen-with-qt/#comments</comments>
		<pubDate>Mon, 10 Sep 2007 14:26:47 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/2007/09/10/centering-a-window-on-the-screen-with-qt/</guid>
		<description><![CDATA[Yet another thing that&#8217;s not automagic in Qt. Here&#8217;s a python solution: if __name__ == &#34;__main__&#34;: &#160; &#160;app = QtGui.QApplication&#40;sys.argv&#41; &#160; &#160;dw = app.desktop&#40;&#41;.width&#40;&#41; &#160; &#160;dh = app.desktop&#40;&#41;.height&#40;&#41; &#160; &#160;myapp = MainWindow&#40;&#41; &#160; &#160;myapp.setGeometry&#40; &#160; &#160; &#160; &#160; &#160;int&#40;&#40;dw - &#40;dw - &#40;dw / 2&#41;&#41; * 1.5&#41; / 2&#41;, &#160; &#160; &#160; &#160; &#160;int&#40;&#40;dh - [...]]]></description>
			<content:encoded><![CDATA[<p>Yet another thing that&#8217;s not automagic in Qt.<br />
Here&#8217;s a python solution:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:<br />
<br />
&nbsp; &nbsp;app <span style="color: #66cc66;">=</span> QtGui.<span style="color: black;">QApplication</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp;dw <span style="color: #66cc66;">=</span> app.<span style="color: black;">desktop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">width</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;dh <span style="color: #66cc66;">=</span> app.<span style="color: black;">desktop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">height</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp;myapp <span style="color: #66cc66;">=</span> MainWindow<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;myapp.<span style="color: black;">setGeometry</span><span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>dw - <span style="color: black;">&#40;</span>dw - <span style="color: black;">&#40;</span>dw / <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> * <span style="color: #ff4500;">1.5</span><span style="color: black;">&#41;</span> / <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>dh - <span style="color: black;">&#40;</span>dh - <span style="color: black;">&#40;</span>dh / <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> * <span style="color: #ff4500;">1.5</span><span style="color: black;">&#41;</span> / <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>dw - <span style="color: black;">&#40;</span>dw / <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> * <span style="color: #ff4500;">1.5</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>dh - <span style="color: black;">&#40;</span>dh / <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> * <span style="color: #ff4500;">1.5</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;myapp.<span style="color: black;">show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span>app.<span style="color: black;">exec_</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></div></div>
<p>This will also resize the window, adapting to the desktop size.<br />
Found and adapted from <a href="http://lists.trolltech.com/qt-interest/2003-08/msg00011.html">the Qt interest archive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2007/09/10/centering-a-window-on-the-screen-with-qt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding Scrollbars to a QFrame in Qt</title>
		<link>http://foobar.lu/wp/2007/09/10/adding-scrollbars-to-a-qframe-in-qt/</link>
		<comments>http://foobar.lu/wp/2007/09/10/adding-scrollbars-to-a-qframe-in-qt/#comments</comments>
		<pubDate>Mon, 10 Sep 2007 09:51:23 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/2007/09/10/adding-scrollbars-to-a-qframe-in-qt/</guid>
		<description><![CDATA[Many things are very easy to accomplish in Qt. Qt&#8217;s designer is a great help with that. But the is no option to simply &#8220;enable&#8221; scrollbars for a frame. Also, the QScrollArea can nowhere be found in the designer. The solution is actually quite simple: Add the component you want to be scrollable (QFrame, QLabel, [...]]]></description>
			<content:encoded><![CDATA[<p>Many things are very easy to accomplish in Qt. Qt&#8217;s designer is a great help with that. But the is no option to simply &#8220;enable&#8221; scrollbars for a frame. Also, the QScrollArea can nowhere be found in the designer. The solution is actually quite simple:</p>
<ol>
<li>Add the component you want to be scrollable (QFrame, QLabel, &#8230;) in the designer as usual</li>
<li>In the application code:
<ol type="a">
<li>Create a new QScrollArea</li>
<li>Set the parent of the widget you created in the designer to &#8220;None&#8221;</li>
<li>Set the widget of the QScrollArea to the widget from step 1</li>
<li>Insert the QScrollArea to you ui</li>
</ol>
</li>
</ol>
<p>And here&#8217;s some example code (boiled down to the essentials):</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sa <span style="color: #66cc66;">=</span> QtGui.<span style="color: black;">QScrollArea</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<span style="color: #008000;">self</span>.<span style="color: black;">ui</span>.<span style="color: black;">myWidget</span>.<span style="color: black;">setParent</span><span style="color: black;">&#40;</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span><br />
sa.<span style="color: black;">setWidget</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">ui</span>.<span style="color: black;">myWidget</span><span style="color: black;">&#41;</span><br />
<span style="color: #008000;">self</span>.<span style="color: black;">ui</span>.<span style="color: black;">vboxlayout1</span>.<span style="color: black;">insertWidget</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> sa<span style="color: black;">&#41;</span></div></div>
<p>You would probably write this somewhere in you application-constructor right after you call <tt>setupUi</tt>.</p>
<p>This will insert the scroll area at the top of vboxlayout1 (see <a href="http://www.riverbankcomputing.com/Docs/PyQt4/html/qboxlayout.html#insertWidget">the doc for insertWidget</a>). You can of course also use <a href="http://www.riverbankcomputing.com/Docs/PyQt4/html/qboxlayout.html#addWidget">addWidget</a>.</p>
<p>It&#8217;s a shame that there&#8217;s no direct support for QScrollArea in designer. Maybe we will see it in some future release.</p>
<p>An example for C++ can be found <a href="http://www.qtforum.org/printout/17574/1/How-to-use-QScrollArea-from-QT-Designer.html">in the Qt Forums</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2007/09/10/adding-scrollbars-to-a-qframe-in-qt/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Deploying PyQt applications on Windows</title>
		<link>http://foobar.lu/wp/2007/07/12/deploying-pyqt-applications-on-windows/</link>
		<comments>http://foobar.lu/wp/2007/07/12/deploying-pyqt-applications-on-windows/#comments</comments>
		<pubDate>Thu, 12 Jul 2007 11:54:01 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/2007/07/12/deploying-pyqt-applications-on-windows/</guid>
		<description><![CDATA[My preferred way to deploy python applications on Windows is to use py2exe. py2exe is a Python Distutils extension which converts Python scripts into executable Windows programs, able to run without requiring a Python installation. If you run in trouble with sip, read on&#8230; Sure there are other options to create windows executables. The ones [...]]]></description>
			<content:encoded><![CDATA[<p>My preferred way to deploy python applications on Windows is to use <a href="http://www.py2exe.org/">py2exe</a>.</p>
<blockquote><p>py2exe is a Python Distutils extension which converts Python scripts into executable Windows programs, able to run without requiring a Python installation.</p></blockquote>
<p>If you run in trouble with <tt>sip</tt>, read on&#8230;<br />
<span id="more-7"></span><br />
Sure there are other options to create windows executables. The ones I know of:</p>
<ul>
<li>Freeze (which comes with python)</li>
<li><a href="http://pyinstaller.hpcf.upr.edu/cgi-bin/trac.cgi">PyInstaller</a></li>
<li><a href="http://starship.python.net/crew/atuining/cx_Freeze/index.html">cx_Freeze</a></li>
<li><a href="http://py2exe.org">py2exe</a></li>
<li><a href="http://effbot.org/zone/exemaker.htm">ExeMaker</a></li>
</ul>
<h3>py2exe</h3>
<p>The reason why I prefer py2exe, and why I would recommend using it, is because it&#8217;s right now the most widely used tool. So you will find lots of hits when googling for it. This is a big bonus. Additionally, it&#8217;s configuration is very flexible, and works well with dependancies (let&#8217;s say you are using SQLAlchemy, or some other third-party python-module).</p>
<p>The others either did not offer enough flexibility or had trouble detecting imported modules. With <em>Freeze</em> I was not even able to get the program to compile following their example scripts.</p>
<h3>py2exe with PyQt</h3>
<p>So you have a Qt program written in python and it works on your machine? Great! To get this to work you actually need to have the Qt libraries and the Python interpreter installed. But you don&#8217;t necessarily want your end-users to install these. To prevent that, you can use py2exe which will give you a directory with all the required libraries, byte-compiled sources and a ready-to-use windows-executable.</p>
<p>In order to create an executable, you write a standard python distutils setup script:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">distutils</span>.<span style="color: black;">core</span> <span style="color: #ff7700;font-weight:bold;">import</span> setup<br />
<span style="color: #ff7700;font-weight:bold;">import</span> py2exe<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp;windows <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;script&quot;</span>: <span style="color: #483d8b;">&quot;MyApplication.py&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp;<span style="color: black;">&#41;</span></div></div>
<p>Then you can create the executable running the setup script with &#8220;py2exe&#8221; as build target:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ python setup.py py2exe</div></div>
<p>With Qt you will run into trouble however. You will most certainly get an error along the lines:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; File <span style="color: #483d8b;">&quot;mainwindow.pyc&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">11</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> ?<br />
&nbsp; File <span style="color: #483d8b;">&quot;qt.pyc&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">9</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> ?<br />
&nbsp; File <span style="color: #483d8b;">&quot;qt.pyc&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">7</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> __load<br />
<span style="color: #008000;">ImportError</span>: No module named sip</div></div>
<p>The reason here is that the <tt>sip</tt> module is required by PyQt, and it&#8217;s not found in a place where py2exe could see that. So you need to tell py2exe to include <tt>sip</tt> even though it does not seem to be imported anywhere:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">distutils</span>.<span style="color: black;">core</span> <span style="color: #ff7700;font-weight:bold;">import</span> setup<br />
<span style="color: #ff7700;font-weight:bold;">import</span> py2exe<br />
setup<span style="color: black;">&#40;</span><br />
&nbsp; &nbsp;windows <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;script&quot;</span>: <span style="color: #483d8b;">&quot;MyApplication.py&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp;options <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;py2exe&quot;</span>:<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;includes&quot;</span>:<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;sip&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span><span style="color: black;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: black;">&#41;</span></div></div>
<p>This will take care of this problem, an your application should run just fine on windows.</p>
<h3>Note</h3>
<p>py2exe will give you a list of additional dll&#8217;s that <em>may</em> be needed. So far I could live without these dll&#8217;s. If you want to be on the safe side, you could include those dll&#8217;s into your project. But with the python-interpreter and the Qt libraries, your project will already be bloated enough (usually around 20MB). So there&#8217;s no need to waste even more space. But, as always, your mileage may vary!</p>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2007/07/12/deploying-pyqt-applications-on-windows/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Writing Qt apps in python</title>
		<link>http://foobar.lu/wp/2007/07/02/writing-qt-apps-in-python/</link>
		<comments>http://foobar.lu/wp/2007/07/02/writing-qt-apps-in-python/#comments</comments>
		<pubDate>Mon, 02 Jul 2007 20:20:23 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/2007/07/02/writing-qt-apps-in-python/</guid>
		<description><![CDATA[Writing Qt apps in Python with Qt3 worked. Somewhat. I never found the energy to get it all set up. Finally with Qt4 we have something that &#8220;just works&#8221;. At least on Ubuntu and Windows (haven&#8217;t tested anywhere else). Yes, since version 4, trolltech finally decided to release Qt as well under the GPL. To [...]]]></description>
			<content:encoded><![CDATA[<p>Writing Qt apps in Python with Qt3 worked. Somewhat. I never found the energy to get it all set up. Finally with Qt4 we have something that &#8220;just works&#8221;. At least on Ubuntu and Windows (haven&#8217;t tested anywhere else).</p>
<p>Yes, since version 4, trolltech finally decided to release Qt as well under the GPL. To most of you it&#8217;s all old news. But hey&#8230;. just felt like writing it down again <img src='http://foobar.lu/wp/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>The problems with SIP are finally gone. So you just install python, Qt4 and pyqt4 and off you go.</p>
<p><span id="more-10"></span></p>
<p>Writing apps is actually a breeze. You fire up the Qt-Designer, drag and drop some widgets on your form, and save the Form as a .ui file.</p>
<p>Next you generate the python-code for the form with pyuic4. Let&#8217;s say you created &#8220;MainForm.ui&#8221;. The you just do:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># pyuic4 MainForm.ui &amp;gt; ui_mainform.py</div></div>
<p>Actually the name &#8220;ui_mainform.py&#8221; is fully up to you.</p>
<p>But this script does not have an entry-point, so just typing &#8220;python ui_mainform.py&#8221; will silently return. For those of you that just thought: &#8220;Hey, I read the man-page, and used the &#8220;-x&#8221; parameter with pyuic4&#8243;.  Sure. You can do that. But you shouldn&#8217;t. Just bear with me a second.</p>
<p>The cleanest way to run your application is to write a startup script. A copy/paste example:</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span><br />
<span style="color: #ff7700;font-weight:bold;">from</span> PyQt4 <span style="color: #ff7700;font-weight:bold;">import</span> QtCore<span style="color: #66cc66;">,</span> QtGui<br />
<span style="color: #ff7700;font-weight:bold;">from</span> ui_mainform <span style="color: #ff7700;font-weight:bold;">import</span> Ui_MainWindow<br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> MyForm<span style="color: black;">&#40;</span>QtGui.<span style="color: black;">QMainWindow</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp;<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> parent<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; QtGui.<span style="color: black;">QWidget</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> parent<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">ui</span> <span style="color: #66cc66;">=</span> Ui_MainWindow<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">ui</span>.<span style="color: black;">setupUi</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp;app <span style="color: #66cc66;">=</span> QtGui.<span style="color: black;">QApplication</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;myapp <span style="color: #66cc66;">=</span> MyForm<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;myapp.<span style="color: black;">show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span>app.<span style="color: black;">exec_</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></div></div>
<h3>So why not just &#8220;pyuic4 -x&#8221; ?</h3>
<p>Simple. Whenever you run this, you will overwrite your old code. And you will inevitably want to complement your user-interface with some program logic. Otherwise your application won&#8217;t do much. So if you put your business-logic into the generated code, you will always end up cutting and pasting things about. And that clearly violates the &#8220;Don&#8217;t repeat yourself&#8221; dogma. So: You be nice, take the startup script and stick your logic in there. Like that you can recreate/regenerate the user-interface from the .ui file without ever (well&#8230; nearly) touching yor business-logic-code.</p>
<p>For some programming examples, head right over to <a href="http://www.rkblog.rk.edu.pl/w/p/python/" title="Riklaunim's TechBlog">Riklaunim&#8217;s TechBlog</a>. There&#8217;s some most excellent examples for pyqt4. You might see, I &#8220;borrowed&#8221; the startup script from there too!</p>
<h3>A note for Windows users</h3>
<p>To get python and Qt working, you need to take care of the version numbers mentioned in the file names of pyqt. Please use the proper Qt version with your pyqt download</p>
<p>As you might have noticed, you also need MingW (a free GNU build environment for windows. Includes C-compiler, libraries, yadda yadda&#8230;). Somewhere along the installation, you might get an error nagging you about the win32api. You can happily ignore this and just continue. I have not yet encountered any problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2007/07/02/writing-qt-apps-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Runnning a twisted application as windows service</title>
		<link>http://foobar.lu/wp/2007/06/27/runnning-a-twisted-application-as-windows-service/</link>
		<comments>http://foobar.lu/wp/2007/06/27/runnning-a-twisted-application-as-windows-service/#comments</comments>
		<pubDate>Wed, 27 Jun 2007 12:47:20 +0000</pubDate>
		<dc:creator>exhuma.twn</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://foobar.lu/wp/2007/06/27/runnning-a-twisted-application-as-windows-service/</guid>
		<description><![CDATA[Currently I am a bit busy, so I will just dump the post I found on usenet. Eventually I will clean it up&#8230; On Wed, 22 Oct 2003 12:24:42 -0600 "Justin Johnson" &#60;justinjohnson@fastmail.fm&#62; wrote: &#62; The general consensus on the mailing list archives seems to be that &#62; I'd need to setup my code to [...]]]></description>
			<content:encoded><![CDATA[<p>Currently I am a bit busy, so I will just dump the post I found on usenet. Eventually I will clean it up&#8230;</p>
<pre>On Wed, 22 Oct 2003 12:24:42 -0600
"Justin Johnson" &lt;justinjohnson@fastmail.fm&gt; wrote:

&gt; The general consensus on the mailing list archives seems to be that
&gt; I'd need to setup my code to not require twistd but just run
&gt; standalone.

Uh. *Maybe* that's the consensus, but it's not actually correct. You can
have a tap or tac run as a NT service.

Lets say you have  a script "server.py" that is runnable with "twistd
-y", you can do (and similar code will work for TAPs):</pre>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">os</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> win32serviceutil<span style="color: #66cc66;">,</span> win32service<br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> MyService<span style="color: black;">&#40;</span>win32serviceutil.<span style="color: black;">ServiceFramework</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;NT Service.&quot;&quot;&quot;</span><br />
<br />
&nbsp; &nbsp; _svc_name_ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;MyService&quot;</span><br />
&nbsp; &nbsp; _svc_display_name_ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;MyService server&quot;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> SvcDoRun<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">import</span> server<br />
&nbsp; &nbsp; &nbsp; &nbsp; f <span style="color: #66cc66;">=</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>server.<span style="color: black;">rootPath</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;cyberhigh.log&quot;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">python</span>.<span style="color: black;">log</span> <span style="color: #ff7700;font-weight:bold;">import</span> startLogging<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">application</span>.<span style="color: black;">app</span> <span style="color: #ff7700;font-weight:bold;">import</span> startApplication<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span> <span style="color: #ff7700;font-weight:bold;">import</span> reactor<br />
&nbsp; &nbsp; &nbsp; &nbsp; startLogging<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; startApplication<span style="color: black;">&#40;</span>server.<span style="color: black;">application</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; reactor.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> SvcStop<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">ReportServiceStatus</span><span style="color: black;">&#40;</span>win32service.<span style="color: black;">SERVICE_STOP_PENDING</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span> <span style="color: #ff7700;font-weight:bold;">import</span> reactor<br />
&nbsp; &nbsp; &nbsp; &nbsp; reactor.<span style="color: black;">stop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:<span style="color: #66cc66;">&lt;</span>/pre<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; win32serviceutil.<span style="color: black;">HandleCommandLine</span><span style="color: black;">&#40;</span>MyService<span style="color: black;">&#41;</span><span style="color: #66cc66;">&lt;</span>/pre<span style="color: #66cc66;">&gt;</span></div></div>
<pre>
--
Itamar Shtull-Trauring    http://itamarst.org/
Available for Python &amp; Twisted consulting</pre>
<p><span class="postbody"></span><span class="postbody"><br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://foobar.lu/wp/2007/06/27/runnning-a-twisted-application-as-windows-service/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

