<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Moshe&#8217;z</title>
	<atom:link href="https://moshez.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://moshez.wordpress.com</link>
	<description>Where Moshe Z knows your name</description>
	<lastBuildDate>Sat, 05 May 2018 18:48:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='moshez.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>https://s0.wp.com/i/buttonw-com.png</url>
		<title>Moshe&#8217;z</title>
		<link>https://moshez.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="https://moshez.wordpress.com/osd.xml" title="Moshe&#039;z" />
	<atom:link rel='hub' href='https://moshez.wordpress.com/?pushpress=hub'/>
	<item>
		<title>New site, new blog, new book</title>
		<link>https://moshez.wordpress.com/2018/05/05/new-site-new-blog-new-book/</link>
					<comments>https://moshez.wordpress.com/2018/05/05/new-site-new-blog-new-book/#respond</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Sat, 05 May 2018 18:48:02 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1339</guid>

					<description><![CDATA[Most of my blogging is now done on my new blog. My &#8220;main website&#8221; is now Cobordism I have a new book out!]]></description>
										<content:encoded><![CDATA[<ul>
<li>Most of my blogging is now done on <a href="https://orbifold.xyz">my new blog.</a></li>
<li>My &#8220;main website&#8221; is now <a href="https://cobordism.com">Cobordism</a></li>
<li>I have a new <a href="https://gumroad.com/l/BVOGd/">book</a> out!</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2018/05/05/new-site-new-blog-new-book/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
		<item>
		<title>My Little Subclass: Inheritance is Magic</title>
		<link>https://moshez.wordpress.com/2017/04/29/my-little-subclass-inheritance-is-magic/</link>
					<comments>https://moshez.wordpress.com/2017/04/29/my-little-subclass-inheritance-is-magic/#respond</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Sat, 29 Apr 2017 08:13:40 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1337</guid>

					<description><![CDATA[New post on my blog.]]></description>
										<content:encoded><![CDATA[<p>New post <a href="https://orbifold.xyz/my-little-subclass.html">on my blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2017/04/29/my-little-subclass-inheritance-is-magic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
		<item>
		<title>Twisted Tutorial Webinar</title>
		<link>https://moshez.wordpress.com/2017/04/19/twisted-tutorial-webinar/</link>
					<comments>https://moshez.wordpress.com/2017/04/19/twisted-tutorial-webinar/#respond</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Wed, 19 Apr 2017 03:14:43 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1331</guid>

					<description><![CDATA[Glyph and I are giving a tutorial about Twisted and web services at PyCon. In order to try it out, we are giving a webinar. Please come, learn, and let us know if you like it!]]></description>
										<content:encoded><![CDATA[<p>Glyph and I are giving a tutorial about Twisted and web services at <a href="https://us.pycon.org/2017/schedule/presentation/120/">PyCon</a>. In order to try it out, we are giving a <a href="https://txwebinar.github.io/">webinar</a>. Please come, learn, and let us know if you like it!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2017/04/19/twisted-tutorial-webinar/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
		<item>
		<title>PYTHONPATH Considered Harmful</title>
		<link>https://moshez.wordpress.com/2017/04/13/pythonpath-considered-harmful/</link>
					<comments>https://moshez.wordpress.com/2017/04/13/pythonpath-considered-harmful/#respond</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Thu, 13 Apr 2017 01:27:43 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1328</guid>

					<description><![CDATA[Another post on my new blog.]]></description>
										<content:encoded><![CDATA[<p>Another <a href="https://orbifold.xyz/pythonpath.html" target="_blank">post on my new blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2017/04/13/pythonpath-considered-harmful/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
		<item>
		<title>Shipping Python Applications in Docker</title>
		<link>https://moshez.wordpress.com/2017/03/20/shipping-python-applications-in-docker/</link>
					<comments>https://moshez.wordpress.com/2017/03/20/shipping-python-applications-in-docker/#respond</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Mon, 20 Mar 2017 01:36:43 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1325</guid>

					<description><![CDATA[Posted on my new blog as an experiment!]]></description>
										<content:encoded><![CDATA[<p>Posted on my <a href="https://orbifold.xyz/python-docker.html">new blog</a> as an experiment!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2017/03/20/shipping-python-applications-in-docker/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
		<item>
		<title>On Raising Exceptions in Python</title>
		<link>https://moshez.wordpress.com/2016/12/10/on-raising-exceptions-in-python/</link>
					<comments>https://moshez.wordpress.com/2016/12/10/on-raising-exceptions-in-python/#respond</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Sat, 10 Dec 2016 04:42:23 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1296</guid>

					<description><![CDATA[There is a lot of Python code in the wild which does something like: raise SomeException("Could not fraz the buzz:" "{} is less than {}".format(foo, quux) This is, in general, a bad idea. Exceptions are not program panics. While they sometimes do terminate the program, or the execution thread with a traceback, they are different [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>There is a lot of Python code in the wild which does something like:</p>
<pre>raise SomeException("Could not fraz the buzz:"
                    "{} is less than {}".format(foo, quux)</pre>
<p>This is, in general, a bad idea. Exceptions are not program panics. While they sometimes do terminate the program, or the execution thread with a traceback, they are different in that they <em>can be caught. </em>The code that catches the exception will sometimes have a way to recover: for example, maybe it&#8217;s not that important for the application to fraz the buzz if foo is 0. In that case, the code would look like:</p>
<pre>try:
    some_function()
except SomeException as e:
    if ???</pre>
<p>Oh, right. We do not have direct access to foo. If we formatted better, using repr, at least we could tell the difference between 0 and &#8220;0&#8221;: but we still would have to start parsing the representation out of the string.</p>
<p>Because of this, in general, it is better to raise exceptions like this:</p>
<pre>raise SomeException("Could not fraz the buzz: foo is too small", foo, quux)</pre>
<p>This way exception handling has a lot of power: it can introspect foo, introspect quux <em>and</em> introspect the string. If by some reason the exception class is raised and we want to verify the reason, checking string equality, while not ideal, is still better than trying to match string parts or regular expression matching.</p>
<p>When the exception is presented to the user interface, in that case, it will not look as nice. Exceptions, in general, should reach the UI only in extreme circumstances: and in those cases, having something that has as much information is useful for root cause analysis.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2016/12/10/on-raising-exceptions-in-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
		<item>
		<title>Moshe&#8217;z Messaging Preferences</title>
		<link>https://moshez.wordpress.com/2016/12/08/moshez-messaging-preferences/</link>
					<comments>https://moshez.wordpress.com/2016/12/08/moshez-messaging-preferences/#comments</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Thu, 08 Dec 2016 03:03:12 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1294</guid>

					<description><![CDATA[The assumption here is that you have my phone number. If you don&#8217;t have my phone number, and you think that&#8217;s an oversight on my part, please send me an e-mail at zadka.moshe@gmail.com and ask for it. If you don&#8217;t have my phone number because I don&#8217;t know you, I am usually pretty responsive on [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The assumption here is that you have my phone number. If you don&#8217;t have my phone number, and you think that&#8217;s an oversight on my part, please send me an <a href="mailto:zadka.moshe@gmail.com">e-mail</a> at <a href="mailto:zadka.moshe@gmail.com">zadka.moshe@gmail.com</a> and ask for it. If you don&#8217;t have my phone number because I don&#8217;t know you, I am usually pretty responsive on e-mail.</p>
<p>In order of preference:</p>
<ul>
<li><a href="https://www.messenger.com/">FB Messenger</a>: you can use it <a href="https://www.facebook.com/help/messenger-app/1526848634305688">without a Facebook account</a>.</li>
<li><a href="https://www.whatsapp.com/">WhatsApp</a></li>
<li><a href="https://whispersystems.org/">Signal</a></li>
<li><a href="https://hangouts.google.com/">Google Hangouts</a></li>
<li>SMS Message</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2016/12/08/moshez-messaging-preferences/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
		<item>
		<title>Don&#8217;t Mock the UNIX Filesystem</title>
		<link>https://moshez.wordpress.com/2016/12/02/dont-mock-the-unix-filesystem/</link>
					<comments>https://moshez.wordpress.com/2016/12/02/dont-mock-the-unix-filesystem/#comments</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Fri, 02 Dec 2016 05:34:28 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1283</guid>

					<description><![CDATA[When writing unit tests, it is good to call functions with &#8220;mocks&#8221; or &#8220;fakes&#8221; &#8212; objects with equivalent interface but a simple, &#8220;fake&#8221; implementation. For example, instead of a real socket object, something that has recv() but returns &#8220;hello&#8221; the first time, and an empty string the second time. This is great! Instead of testing [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>When writing unit tests, it is good to call functions with &#8220;mocks&#8221; or &#8220;fakes&#8221; &#8212; objects with equivalent interface but a simple, &#8220;fake&#8221; implementation. For example, instead of a real socket object, something that has recv() but returns &#8220;hello&#8221; the first time, and an empty string the second time. This is great! Instead of testing the vagaries of the other side of a socket connection, you can focus on testing your code &#8212; and force your code to handle corner cases, like recv() returning partial messages, that happen rarely on the same host (but not so rarely in more complex network environments).</p>
<p>There is one OS interface which it is wise not to mock &#8212; the venerable UNIX file system. Mocking the file system is the classic case of low-ROI effort:</p>
<ul>
<li>It is easy to isolate: if functions get a parameter of &#8220;which directory to work inside&#8221;, tests can use a per-suite temporary directory. Directories are cheap to create and destroy.</li>
<li>It is reliable: the file system rarely fails &#8212; and if it does, your code is likely to get weird crashes anyway.</li>
<li>The surface area is enormous: open(), but also os.open, os.mkdir, os.rename, os.mknod, os.rename, shutil.copytree and others, plus modules calling out to C functions which call out to C&#8217;s fopen().</li>
</ul>
<p>The first two items decrease the Return, since mocking the file system does not make the tests easier to write or the test run more reproducible, while the last one increases the Investment.</p>
<p>Do not mock the file system, or it will mock you back.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2016/12/02/dont-mock-the-unix-filesystem/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
		<item>
		<title>Belt &#038; Suspenders: Why put a .pex file inside a Docker container?</title>
		<link>https://moshez.wordpress.com/2016/11/19/belt-suspenders-why-put-a-pex-file-inside-a-docker-container/</link>
					<comments>https://moshez.wordpress.com/2016/11/19/belt-suspenders-why-put-a-pex-file-inside-a-docker-container/#respond</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Sat, 19 Nov 2016 05:11:36 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1254</guid>

					<description><![CDATA[Recently I have been talking about deploying Python, and some people had the reasonable question: if a .pex file is used for isolating dependencies, and a Docker container is used for isolating dependencies, why use both? Isn&#8217;t it redundant? Why use containers? I really like glyph&#8217;s explanation for containers: they isolate not just the filesystem stack [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Recently I have been talking about deploying Python, and some people had the reasonable question: if a .pex file is used for isolating dependencies, and a Docker container is used for isolating dependencies, why use both? Isn&#8217;t it redundant?</p>
<h3>Why use containers?</h3>
<p>I really like <a href="https://glyph.twistedmatrix.com/2016/10/what-am-container.html">glyph&#8217;s</a> explanation for containers: they isolate not just the filesystem stack but the processes and the network, giving a lot of the power that UNIX was supposed to give but missed out on. Containers isolate the file system, making it easier for code to write/read files from known locations. For example, its log files will be carefully segregated, and can be moved to arbitrary places by the operator without touching the code.</p>
<p>The other part is that none of the reasonable options packages <em>Python </em>and this means that a pex file would still have to be tested with multiple Pythons, and perhaps do some checking at start-up that it is using the right interpreter. If PyPy is the right choice, it is the choice the operator would have to make and implement.</p>
<h3>Why use pex?</h3>
<p>Containers are an easy sell. They are right on the hype train. But if we use containers, what use is pex?</p>
<p>In order to explain, it is worthwhile comparing a <a href="https://glyph.twistedmatrix.com/2015/03/docker-deploy-double-dutch.html">correctly built</a> runtime container that is not using pex, with one <a href="https://moshez.wordpress.com/2016/11/13/deploying-with-twisted-saying-hello/">that is</a>: (parts that are not relevant have been removed)</p>
<pre>ADD wheelhouse /wheelhouse
RUN . /appenv/bin/activate; \
    pip install --no-index -f wheelhouse DeployMe
</pre>
<pre>COPY twist.pex /
</pre>
<p>Note that in the first option, we are left with extra gunk in the /wheelhouse directory. Note also that we still have to have pip and virtualenv installed in the runtime container. Pex files bring the double-dutch philosophy to its logical conclusion: do even more of the build on the builder side, do even less of it on the runtime side.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2016/11/19/belt-suspenders-why-put-a-pex-file-inside-a-docker-container/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
		<item>
		<title>Deploying with Twisted: Saying Hello</title>
		<link>https://moshez.wordpress.com/2016/11/13/deploying-with-twisted-saying-hello/</link>
					<comments>https://moshez.wordpress.com/2016/11/13/deploying-with-twisted-saying-hello/#comments</comments>
		
		<dc:creator><![CDATA[moshez]]></dc:creator>
		<pubDate>Sun, 13 Nov 2016 15:31:22 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://moshez.wordpress.com/?p=1247</guid>

					<description><![CDATA[Too Long: Didn&#8217;t Read The build script builds a Docker container, moshez/sayhello:. $ ./build MY_VERSION $ docker run --rm -it --publish 8080:8080 \ moshez/sayhello:MY_VERSION --port 8080 There will be a simple application running on port 8080. If you own the domain name hello.example.com, you can point it at a machine that the domain resolves to [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="too-long-didn-t-read" class="section">
<h2>Too Long: Didn&#8217;t Read</h2>
<p>The <code>build</code> script builds a Docker container, <code>moshez/sayhello:</code>.</p>
<pre class="code literal-block">$ ./build MY_VERSION
$ docker run --rm -it --publish 8080:8080 \
  moshez/sayhello:MY_VERSION --port 8080
</pre>
<p>There will be a simple application running on port 8080.</p>
<p>If you own the domain name <code>hello.example.com</code>, you can point it at a machine that the domain resolves to and then run:</p>
<pre class="code literal-block">$ docker run --rm -it --publish 443:443 \
  moshez/sayhello:MY_VERSION --port le:/srv/www/certs:tcp:443 \
  --empty-file /srv/www/certs/hello.example.com.pem
</pre>
<p>It will result in the same application running on a secure web site: <code>https://hello.example.com</code>.</p>
</div>
<p>&nbsp;</p>
<p>All source code is available on <a href="https://github.com/moshez/sayhello">GitHub</a>.</p>
<div id="introduction" class="section">
<h2>Introduction</h2>
<p><a class="reference external" href="https://wsgi.readthedocs.io/en/latest/">WSGI</a> has been a successful standard. Very successful. It allows people to write Python applications using many frameworks (<a class="reference external" href="https://www.djangoproject.com/">Django</a>, <a class="reference external" href="http://docs.pylonsproject.org/en/latest/docs/pyramid.html#pyramid-documentation">Pyramid</a>, <a class="reference external" href="http://flask.pocoo.org/">Flask</a> and <a class="reference external" href="https://bottlepy.org/docs/dev/">Bottle</a>, to name but a few) and deploy using many different servers (<a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/">uwsgi</a>, <a class="reference external" href="http://gunicorn.org/">gunicorn</a> and <a class="reference external" href="https://modwsgi.readthedocs.io/en/develop/">Apache</a>).</p>
<p><a class="reference external" href="https://twistedmatrix.com/documents/16.5.0/web/howto/web-in-60/wsgi.html">Twisted</a> makes a good WSGI container. Like Gunicorn, it is pure Python, simplifying deployment. Like Apache, it sports a production-grade web server that does not need a front end.</p>
<p>Modern web applications tend to be complex beasts. In order to be trusted by users, they need to have TLS support, signed by a trusted CA. They also need to transmit a lot of static resources &#8212; images, CSS and JavaScript files, even if all HTML is dynamically generated. Deploying them often requires complicated set-ups.</p>
</div>
<div id="containers" class="section">
<h2>Containers</h2>
<p><a class="reference external" href="https://glyph.twistedmatrix.com/2016/10/what-am-container.html">Container images</a> allow us to package an application with all of its dependencies. They often cause a temptation to use those as the configuration management. However, <a class="reference external" href="https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#/add-or-copy">Dockerfile</a> is a challenging language to write big parts of the application in. People writing WSGI applications probably think Python is a good programming language. The more of the application logic is in Python, the easier it is for a WSGI-based team to master it.</p>
</div>
<div id="pex" class="section">
<h2>PEX</h2>
<p><a class="reference external" href="https://pex.readthedocs.io/en/stable/">Pex</a> is a way to package several Python &#8220;distributions&#8221; (sometimes informally called &#8220;Packages&#8221;, the things that are hosted by <a class="reference external" href="https://pypi.python.org/pypi">PyPI</a>) into one file, optionally with an entry-point so that running the file will call a pre-defined function. It can take an explicit list of wheels but can also, as in our example here, take arguments compatible with the ones <a class="reference external" href="https://pip.pypa.io/en/stable/">pip</a> takes. The best practice is to give it a list of wheels, and build the wheels with <code>pip wheel</code>.</p>
</div>
<div id="pkg-resources" class="section">
<h2>pkg_resources</h2>
<p>The <a class="reference external" href="https://setuptools.readthedocs.io/en/latest/pkg_resources.html">pkg_resources</a> module allows access to files packaged in a distribution in a way that is agnostic to how the distribution was deployed. Specifically, it is possible to install a distribution as a <a class="reference external" href="https://docs.python.org/2/library/zipimport.html">zipped directory</a>, instead of unpacking it into <code>site-packages</code>. The code:<cite>pex</cite> format relies on this feature of Python, so adherence to using <code>pkg_resources</code> to access <a class="reference external" href="https://docs.python.org/2/distutils/setupscript.html#installing-package-data">data files</a> is important in order to not break code:<cite>pex</cite> compatibility.</p>
</div>
<div id="let-s-encrypt" class="section">
<h2>Let&#8217;s Encrypt</h2>
<p><a class="reference external" href="https://letsencrypt.org/donate/">Let&#8217;s Encrypt</a> is a free, automated, and open Certificate Authority. It has invented the <a class="reference external" href="https://github.com/letsencrypt/acme-spec">ACME</a> protocol in order to make getting secure certificates a simple operation. <a class="reference external" href="https://txacme.readthedocs.io/en/latest/">txacme</a> is an implementation of an ACME client, i.e., something that asks for certificates, for Twisted applications. It uses the <a class="reference external" href="https://twistedmatrix.com/documents/16.5.0/api/twisted.internet.interfaces.IStreamServerEndpointStringParser.html">server endpoint</a> plugin mechanism in order to allow any application that builds a listening endpoint to support ACME.</p>
</div>
<div id="twist" class="section">
<h2>Twist</h2>
<p>The <code>twist</code> command-line tools allows running any Twisted <a class="reference external" href="https://twistedmatrix.com/documents/current/core/howto/tap.html">service plugin</a>. Service plugins allow us to configure a service using Python, a pretty nifty language, while still allowing specific customizations at the point of use via command line parameters.</p>
</div>
<div id="putting-it-all-together" class="section">
<h2>Putting it all together</h2>
<p>Our <code>setup.py</code> files defines a distribution called <code>sayhello</code>. In it, we have three parts:</p>
<ul class="simple">
<li><code>src/sayhello/wsgi.py</code>: A simple Flask-based WSGI application</li>
<li><code>src/sayhello/data/index.html</code>: an HTML file meant to serve as the root</li>
<li><code>src/twisted/plugins/sayhello.py</code>: A Twist plugin</li>
</ul>
<p>There is also some build infrastructure:</p>
<ul class="simple">
<li><code>build</code> is a Python script to run the build.</li>
<li><code>build.docker</code> is a Dockerfile designed to build pex files, but not run as a production server.</li>
<li><code>run.docker</code> is a Dockerfile designed for production container.</li>
</ul>
<p>Note that build does <em>not</em> push the resulting container to DockerHub.</p>
</div>
<div id="credits" class="section">
<h2>Credits</h2>
<p>Glyph Lefkowitz has inspired me in his <a class="reference external" href="https://glyph.twistedmatrix.com/2015/03/docker-deploy-double-dutch.html">blog</a> about how to build efficient containers. He has also <a class="reference external" href="http://pyvideo.org/djangocon-2011/djangocon-2011--keynote---glyph-lefkowitz.html">spoken</a> about how deploying applications should be no more than one file copy.</p>
<p>Tristan Seligmann has written txacme.</p>
<p>Amber &#8220;Hawkowl&#8221; Brown has written &#8220;twist&#8221;, which is much better at running Twisted-based services than the older &#8220;twistd&#8221;.</p>
<p>Of course, all mistakes and problems here are completely my responsibility.</p>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://moshez.wordpress.com/2016/11/13/deploying-with-twisted-saying-hello/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		
		<media:content url="https://1.gravatar.com/avatar/47d49ac4314539cc0ee468a7b8c9210b3926cfef199d96f09ef9580ff6b023bb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">moshez</media:title>
		</media:content>
	</item>
	</channel>
</rss>
