« Return to show page
Transcript for Episode #32:
PyPy.js - PyPy Python in Your Browser
Imagine a future where you are building a rich, client-side web app. You start by creating some backend services in Flask or Node, an HTML page, throw in a few divs and uls, and then you type <script src="main.py" language="Python">. That future might just be possible, for the right types of applications, with Ryan Kelly's pypy.js project. This is Talk Python To Me with guest Ryan Kelly, show number 32, recorded Wednesday, September 30th 2015.
Welcome to Talk Python to Me. A weekly podcast on Python- the language, the libraries, the ecosystem, and the personalities. This is your host, Michael Kennedy, Follow me on twitter where I'm @mkennedy. Keep up with the show and listen to past episodes at talkpython.fm and follow the show on twitter via @talkpython.
This episode is brought to you by Hired and Codeship. Thank them for supporting the show on twitter via @hired_hq and @codeship
1:51 Ryan, welcome to the show.
1:53 Thanks for having me.
1:54 I'm super excited that you are here today, we are going to talk about Python but in a place you typically do not find it- int he browser, right?
2:02 Yeah there is a lot of cool projects out there, and I'm a huge fan of the one that you've been working on. Before we get to that though, let's talk about how you got into programming, what's your story?
2:55 I think a lot of us who are in programming had that experience where maybe we weren't we didn't think that we were programmers per say right, but then you get some experience and then you are like, "Wow, this is really amazing, this is really way more rewarding than a lot of other stuff". I had that experience in math, I studied lots of math and I'm like, "But we don't build anything here", like, programming is so much more concrete but creative, you know. I love it.
3:18 Yeah. Yes, a beautiful combination of creativity, discovering and creating, it's pretty cool.
3:28 Yeah, sure. So how did you get to Python?
3:30 I was handed Python as a requirement for an internship I was doing in university. I went to work for a company that were doing engineering simulations, so I think like a lot of people that sort of came to Python because it has really strong tools for doing analyses and visualizations, so that was in a kind of typical intern project kind of way, it was kind of like, "Here is the relatively well scoped project then you are using this language and off you go". But I just found that it really fit my head, in a way that a lot of other languages that I've been playing around with didn't. It was just super easy to get up and running and dive in and I found that the more time I spent with it, the more I came to understand the language, and you know, find a lot of these more and more interesting corners of it, that just kind of grew from there. And, so the sense from that point, it's always been my kind of go to language for side projects, or projects for I'm not kind of locked into a language for other reasons.
4:30 Yeah, I think that Python has this rare combination of being very capable, and yet very simple. There is a lot of capable languages and there is a lot of simple languages but they don't often intersect, so that's great.
4:44 I've worked in some interesting languages like Prolog and there is a language called Mozart which is like a logic programming language, and they are incredibly powerful but yeah, they don't have that just clarity that Python has.
4:56 So before we get to talk about your project, you work at Mozilla, right?
5:00 That's right.
5:03 Oh, I'm a huge fan of Mozilla, Firefox is definitely my Browser. I tried to spread the word, what do you do there?
6:13 So maybe at a really high level we could just talk about your project PyPy Js and we could talk a little more specifically about it.
7:26 Oh thank you.
7:26 Yeah, definitely. What was the title of it- I forgot.
7:29 PyPy.js What? How? Why? I think from memory.
7:34 Yeah, that's perfect, I think you are right. And it's on the YouTube channel for PyCon US 2015, so I'll be sure to link to that in the show notes. One of the ways you opened your talk when you talked about how Mozilla loves the web and not just the technology of it but sort of the whole idea and the culture of it. Could you maybe talk about that a bit?
7:53 Sure. So we have this saying at Mozilla, this is sort of one of the things that really inspired me to get started on this project. We like to say, "The web is the platform." Or this is kind of the world we want to live in is where the web is the platform. And so the web not necessarily from a technology standpoint but from a kind of computing platform standpoint is pretty unique and pretty amazing. It's a platform that doesn't have any kind of powerful gate keepers, it's a platform where anyone can kind of show up and start participating, you can publish stuff on the web without having to be locked into a particular hardware platform, or a particular set of tools.
9:28 It really is. You know, you could have sold me on this idea with that statement, in 2005, no problem, but I think it's even more relevant now, because we all have these app platforms, and these proprietary APIs, you know, IOS, Android, OS10, like there is just more and more walled gardens in proprietary stuff.
9:53 Walled gardens and app stores.
9:55 Yeah. Absolutely and there is a good financial reason through that, right, I mean-
9:59 Absolutely. And not just financial reasons, like 10:00 content has a lot of user value and security value and stuff like that. So, the web hasn't not completely undeserved reputation as a little bit of a security badlands because you don't know whose code you are running off the time, you just have to trust that the browser is going to do the right thing for you.
14:20 I was present in the audience for that talk and I loved it.
14:23 Yeah, that was an amazing talk. Those of you guys out there listening who haven't seen this, I'll put it in the links in the show notes, I've referenced it before on the show but, he did a really good job of showing of Asm.js and basically bringing anything that can be written in C to the web and one of those ones like a pretty high end video game like Quake, or something like this, right?
14:46 They are doing sort of more- within half the speed of native I think they usually get these things running. It's pretty amazing.
14:55 Yeah. Very very amazing.
15:28 So does this relate to your project PyPy.js?
15:32 The PyPy.js is sort of coming together of what to me are two amazing fields of engineering. One of them was Asm.js and scripting and this whole idea that you can treat the web more or less like a compile target. You know, as if it were a native CPU. The other half of that of course is the PyPy Python interpreter which I think you had an episode on not too long ago.
15:56 That's right, that was show 21, and PyPy the interpreter does some really amazing stuff.
16:02 It's incredible. So, one of the things that I think- actually it was talked about a little bit in that episode, one of the things I really like about PyPy is that they weren't just focused on writing a really fast Python interpreter, they were focused on creating a platform for experimenting with interpreters. So, it seem to me that the perfect kind of opportunity to learn more about both of these- learn more about PyPy and learn more about emscripten and Asm.js. Because PyPy is structured in such way to make it really easy to dive in and kind of change bits in and out and play around with it. I had this idea that I could get in there and I'll just find the Just In Time compiler back end inside PyPy.
17:46 That's so amazing. How long did it take you to get a proof of concept that it was actually doing something?
17:52 I think my very first proof of concept without the JIT compiler part, came together pretty quickly. I lost maybe two weeks trying to figure out that emscripten was actually assigning file descriptors at different numbers than they usually are in unix, so like standard unix is usually file descriptors zero, standard out as usually file descriptor one. I was giving then different numbers because it never mattered before, but PyPy really didn't like it. So if you kind of just like tool chain compatibility problems like that, but so once I got that figured out, right is sort of just compiler as if you were running through a cross compiler and you get it up and running pretty quickly, the JIT back end, I probably worked on and off for the better part of the year I can save this scheme at the end of the PyCon Australia probably three years ago and then I presented the kind of final first version of it at the following PyCon Australia the next year.
18:52 In your presentation, you said your goal was really to bring support to the web for Python. And in your mind that had that to sort of meet three criteria: compatibility, performance and webishness. Can you talk about that?
19:07 I wish I had found a better word for that, but-
19:10 That's the official word, yeah.
21:07 Python has usually got your back.
This episode is brought to you by Hired. Hired is a two-sided, curated marketplace that connects the world's knowledge workers to the best opportunities.
Each offer you receive has salary and equity presented right up front and you can view the offers to accept or reject them before you even talk to the company. Typically, candidates receive 5 or more offers in just the first week and there are no obligations, ever.
Sounds pretty awesome, doesn't it? Well did I mention the signing bonus? Everyone who accepts a job from Hired gets a $2,000 signing bonus. And, as Talk Python listeners, it get's way sweeter! Use the link hired.com/talkpythontome and Hired will double the signing bonus to $4,000!
Opportunity is knocking, visit hired.com/talkpythontome and answer the call.
22:36 Right. So yeah, that's the compatibility aspect and things like parts of the standard libraries, well, you know do you have all of the if a full implementation of the sys module including get frame and kind of the debugger and all of these things. And it's interesting, it's sort of like well I don't really have used those things that often, and I don't really depend on integer overflows, escalating to big ends by default that often, or you know, I don't use sys.getframe that often, but it's interesting as soon as you start trying to run like whole programs on Python, you'll find that you use some libraries somewhere that uses some library or that it happens to use one of those things, in some corner of its API. So even though they seem like edge cases, they are often not at a whole program level.
23:28 Right, they are not necessarily edge cases for small simple things, but if you are going to really write major apps there, then all of a sudden those become things you have to worry about, right?
23:58 Right. Like Script, SQl some file. py, something like this, right?
24:22 Right, absolutely. So it sounds to me like PyPy.js completely nails the compatibility part because it's effectively PyPy, is that right?
24:30 Correct. So the fun thing about basing this on PyPy is essentially get the compatibility part for free, because that put on amazing amount of work into being really really compatible with the Python language reference CPython.
24:43 And then you get to the performance. And performance has multiple aspects. One is, I've got my code loaded up and now I can run this and it's doing xyz iterations per second, with such and such amount of latency. The other part of it is I visit the web page and then it responds, right?
25:06 And so, maybe we could talk about those a bit?
26:18 Right, and so right now, if you look I think you know, you have a really great page Are We Python Yet.com that talks about a lot of cool stuff, we'll get to that, but on there you have the download size both off of disc and sort of maybe on the wire, and on disc it's like it was a little higher but you guys have gone down to 15 MB right, and what is that like 5 on the wire?
26:44 Yeah, I think it's down to the single digits on the wire, I think 5 is probably about right. Which for a native application is not terrible, that's kind of in the 26:58 before stuff you have to load up in order to interact with the webpage it's not great.
27:10 Yes. Usually not measured in megabytes, let's be quite frank about it.
27:15 That's right. That's huge what is that 100 K? No, no, it's 20 MB. But you know, there are potential solutions, right, I mean there are CDNs extreme cashing, could alleviate to somewhat, right, the core runtime parts could somehow be sort of shared across sites.
27:37 Indeed. I think there's actually still a lot low hanging fruit in that size, right, s that size includes for example an entire unicode character database, which is built into the interpreter, in PyPy. You know, includes all of the standard library models that are built into the interpreter whether you are going to use them or not, and things like that. So, there is definitely some scope for making it smaller and I have made more minimal builds of it that are several megabytes smaller. But I think if it is ever going to get down to tens of kilobytes in size, it's pretty unrealistic.
28:16 If you go and download CPython from Python.org, compress that's like 22, 23 MB, right, so you know, if you are going to shift the whole runtime that implementation, the PyPy implementation, that's kind of a lower in some way.
29:11 And the games that are compiled for the web within script have this problem as well, right, you want to get into the game and start playing it, you have got to download many more megabytes of like image assets and compiled code and all these sorts of stuff, but it's ok for that use case. And I think that's sort of the point where we are at with the project now, where people that are sort of really showing an interest in starting to use it are cases where there is going to be less and less of a concern, where you are ok to kind of wait for a few seconds while you are bootstrapping into a fairly elaborate experience.
29:47 Right. And like I said once you get that loaded up the first time, you can cash it. So if you are able to wait 5 seconds, or whatever it takes to download that, then you know, maybe it's possible. So games are obviously one concept here, maybe if you are doing some like I said single page app thing where you kind of load it up and then you just stay there for a long time, kind of like gmail that might be an area. One that you've brought up that was really interesting was IPython.
30:20 So I had some preliminary kind of interactions with the Jupyter and IPython people, we are trying to get this plug in and in a sense actually, they've got really excellent infrastructure for plugging in different language back ends that can do Ruby or whatever plugged into their infrastructure. So that in a sense kind of works, like hey, you can plug in plug PyPy.js and run this completely client side. Of course, what is missing is all of the fun libraries that you might want to use with that, so if you want to do scientific Python on the web, scientific kind of programming on the web in Python you've got to want things like Numpy and sort of all of the analyses libraries that typically go along with that, so I'm still interested in kind of pushing ahead and seeing where we can go with that, but I think it becomes more of a library problem in that point, making sure you can actually ship that, the all of the details of that experience that people would expect. Not just the Python interpreter itself.
31:21 The Python interpreter itself is actually probably the easiest. Because then you've got to get Numpy and SciPy and Scikit-learn and a lot of those have C extensions which then you've got to get in to asm.js again, and there is a lot of nuances that people build in those libraries have never thought of, right?
31:40 Exactly. And so in theory that will all possible, it's all the same principle of you know, we've got code for a native platform, we can re-target for the web, but it's never quite that straightforward in practice.
31:53 Do you want to talk about Are We Python Yet a bit?
31:59 Yeah, so what was the idea, you said that was inspired by some sort of performance metrics at Mozilla historically.
32:46 We were starting to really measure our community contributions and figure out you know, how many contributors we are getting from different parts of the world, how big the community is growing, they set off a metrics checking website called Are we a million yet.com, and so this ongoing habit of just trying to picking things that we really want to make a big difference to and measuring them. And putting it out somewhere for everyone to see. The other folks that are really keen on doing public performance measurements are the PyPy team. So, the benchmarks that are on Are We Python Yet.com are all taken from the PyPy speed center. Which I haven't managed to get all of their benchmarks running but I've got a good subset of them. So both places I guess have really strong history of like being really upfront and public about all of their performance metric structure, I think it's a wonderful philosophy to try and follow the footsteps of.
33:42 Yeah, and you got here and you can really quickly see where the performance is really good, and where it may lag behind and one of the things I thought was really interesting is there are plenty of places where PyPy.js is literally faster than CPython.
34:01 Yeah, all of that magic of course is due to the PyPy JIT and if you change the comparison to compare to a native PyPy of course is going to be uniformly slower. I was pretty amazed, sort of one of the challenges I set myself when I was starting out on this little experiment, was to say look, is the combination of asm.js being almost as fast as a native platform and PyPy being kind of consistently faster than CPython. In combination it means we can actually run Python benchmarks in the web faster than your standard Python interpreter and it's pretty astonishing to find out that that is in fact the case.
This episode is brought to you by Codeship. Codeship has launched organizations, create teams, set permissions for specific team members and improved collaboration in your continuous delivery workflow. Maintains centralized control over your organization's projects and teams with Codeship's new organization's plan.
And as Talk Python listeners, you can save 20% off any premium plan for the next 3 months. Just use the code TALKPYTHON.
Check them out at codeship.com and tell them "thanks" for supporting the show on Twitter where they are at @codeship.
35:35 Yeah, when I pulled this up I was like let's see how many times slower it is is it like something we can live with, because it's going to run int he browser, and I was like, wow ok that's really cool.
35:46 It's also fun to click of the D8 interpreter in those comparisons and get just the spot at money engine and get a little bit more times faster than C Python as well.
35:57 That's awesome, and of course D8 is Chorme and Spider Monkey is Firefox right?
36:06 Same one that runs no js, right? Very interesting. So the performance story is really really good on the execution side, but then you also have the stuff about sort of the startup and the download size and so on.
37:35 I'd love to think I could pull those strings I don't know if I really have them however, I mean the thing about the web- and this has been a general principle of the web for a long time, right, is no one browser vendor really has the power to do that by themselves. So you know, we could kind of put this in the browser and say yeah like we want to treat Python as a first class language, and we are going to special case it int he browser and get a really good experience for Firefox users. But, the individual market share of us or any other browser who try to do that is probably not sufficient for people writing websites to be able to depend on it, right?
38:21 Yeah, absolutely, and the most important use case of that would be on mobile, and then that's an even harder, so...
39:27 That's really, that's the way that it works, right, that's the way the web is successful anyway like you said, people try to gem their way through like IE6 , stuff that happened back in those days but that's not really what sticks.
39:42 You've got have a good story for getting from where the web is to where you want the web to be. And asm.js kind of really came in and provided that. We want to treat the web as a compilation target and here is a pretty ok way of doing it, right. We can get to that point. So now you've got inputs to actually make that better.
40:04 Yeah, a foundation or idea to start from that everybody can start.
40:09 Right, exactly.
40:57 Yeah, the future is going of be future interesting when that sort of takes all.
41:15 Right, and a lot of the stuff that you sort of ship from your site that would have been js files are now binary, right.
41:23 Right, exactly.
41:25 So, Python 2 or Python 3?
41:28 Currently, Python 2. Mostly by default. But that describes me as well as this project, I'm one of the laggards slowly coming to the realization that I'm falling behind and that I still use Python 2 by default everywhere. That said, one of the neat things about this is PyPy team are working really hard on their Python 3 compatibility and so it's a pretty straightforward prospects kind of ride along the co-tails of that work and ship Python 3 in the browser just as easily you can ship Python 2 on top of this technology standard.
42:04 That's great because you are just taking the literally in the PyPy interpreter as it is and sending it through this tool chain like whatever support PyPy has for Python 3 more or less is the support that you have for it, right.
42:18 Right, exactly. Sort of it just comes out at the other end, and that goes for all of the other languages that people are experimenting with on top the PyPy tool chain as well.
42:27 Yeah, I read an interesting article just this week, talking about Python 2 versus Python 3 and you know, there is a lot of practical reasons a lot of people are still doing Python 2 and this article is called "Planing an early death for Python 2" and it had some really interesting ideas, I'll be sure to link to it. But a lot about delay like people culturally think and talk about Python, they are tempting to change that there and I think it was interesting idea anyway, I'll link to that for everyone.
42:52 Yeah, cool. For what it is worth I really noticed the change in the community in the last year or two, whereas kind of Python 3 is- it seems to have kind of broken through in a sense like it's people might look at you a little bit odd if you are not taking Python 3 seriously. This is something I've noticed anyway.
43:10 Yeah, I've definitely noticed the same thing. So, are there notable deployments or places that we can go find that PyPy.js has been used yet or is it too early for that, what's the story around there?
43:23 I think it's broadly too early for that, I mean, you can go to the PyPy.js website and play around with it sort of an interesting project for me, I am sort of in the position of doing a project that I don't really want to build anything with, like the project itself is the point of it for me, so I've been talking to a couple of different people who are interested in trying it out as part of an actual product, in places where you might use something like IPython or sort of one of the other in browser Python environments, currently. But, I don't think any of those are live yet, they have certainly got people showing up and chipping in to the project and trying it out and experimenting with using it in their stuff but I don't think that anyone has kind of put it into production just yet.
44:08 Right, if you want to check out the code it at GitHub.com/pypy.js. So pretty easy to find. Do you see maybe use case in some of the more like offline appish HTML 5 apps so I'm thinking like Firefox OS like Phonegap type platforms.
44:31 Absolutely, so that's one of the places where the startup overhead of this whole infrastructure will be less of a problem. Because you can list the files to be downloaded as a manifest and you kind of get better control over the cashing and things like that. So it probably makes more sense in that sort of contained experience of an app than it does as you know scripting on the open web somewhere.
44:57 Sure, yeah, that definitely seems like it.
44:59 What about Chrome OS?
45:01 To be honest, I haven't thought about it.
45:04 I'm not sure you are allowed to promote them but you these two have sort of prepackaged offline manifest type stuff, so it seems potentially would be good.
45:14 And particularly as the web kind of comes to terms with that packaging of applications, and more standard sort of stuff to emerge around it, then you know, ideally, you don't have to make that distinction like oh, Phonegap or Firefox OS or Chrome OS is kind of like, oh this is how we do packaged apps for the web. And Python has a pace in that ecosystem, that would be a really great outcome.
45:35 That would be absolutely great outcome. There are other sort of Python in the browser type frameworks or attempts or projects, and you listed something like at least nine in your talk. You know, two that are pretty popular are, one is Sculpt js- I had Brad Miller on one of the previous shows to talk about that, and another was Brython. And those seem more like script lang = Python sort of frameworks but they make tradeoffs to make that possible. Can you compare those a bit?
48:20 You did show a way that you could interact with libraries such as JQuery and The Dom, and so on.
48:26 From PyPy.js, right?
49:26 Oh yeah, because maybe you don't need super complicated interaction but like I'd like to grab something under this text box and then display it over here and this selector or whatever, yeah.
49:36 Yeah, for things that are strings and things that are mutable or things that don't really have references back to Python, it's fine. No drama at all.
51:05 Because you are using the same tool set that they use for C, like LLVM compilers and things like that, right?
51:16 Yeah, it's like saying, well when I'm doing C++ how do stuff happening in machine language and assembly- you don't even think about it, right? Same thing here, more or less.
51:26 Right. Exactly.
51:28 Ryan we are kind of coming up near to the end of the show, do you have some maybe call to actions for people out there?
51:36 I'm really interested in connecting with people who want to put this to a concrete use. I think what the project really needs now is kind of 51:46 by concrete use cases. So it's past the point of our own experiment with this fun technologies and see what's possible, see how fat we can make it and things like that. There is still ground to cover but that's kind of the real experimental phase of that is more or less done, and in order to go from experiment to actual product, and for me to like go into the website and remove the word experiment from the description of the project, it really needs to make that jump into something that people actually would be happy to deploy in practice.
52:24 I plan to talk to a couple of people who are doing like Python shows in the web for variety of reasons, who are interested in trying it out, but I'd love to hear of people had Python application, that they feel would be really interesting to pull it to the web. In the same way that you might like take a game that you've got written in Python and package it up with Py2.exe and ship it to your Windows users, right. You've got something that you think of wow, that would be really great if I could just take this python kind of application and port it to the web. I'd love to just kind of talk through the possibilities. I think that's as much as anything that's what the project needs right now. People to come and try and put it to use and see what works well and what doesn't and we'll fix the bits that don't .
53:09 Great call to action. That is what makes projects real, right, when people use them and they have to hit all of the little edgy cases and sort of smooth it out, so it's a real product, right?
53:33 Right. Absolutely. So, another thing that I thought you have as a final call to action in your talk was the concept of filing bugs against the web. Do you maybe want to talk about that really quickly because that's a cool Mozilla idea I think.
53:47 I guess the driving force with this project for me is really that philosophy. So the idea that the web should be a first class computing platform. And a lot of people kind of in the habit of thinking like oh the web can't do this. I really want to do this on the web but it's not going to work because x y z. And it wasn't until I actually started working at Mozilla and it kind of occurred to me that actually the web is a really fluid medium, a lot of people who really care deeply about the web being a really powerful platform and sort of invested in the web not necessarily winning but competing, with native platforms, and it's a change in perspective, right, so you can realize I actually like the fact that the web can't do this, I should consider that a bug, in the web.
54:37 It's one thing to say that and another thing to put it into practice, right, if you come into bugzilla.mozilla.org and like bug, I can't run Python on the web, we may not close it as invalid straightaway, but probably it would be projects like this at big chunk of work. I don't know, it's- I encourage people to expect more from the web, as it's actually getting more and more powerful as an application platform and if there is something that you feel like you should be able to do but can't quite make it work on the web, like find someone at Mozilla or in the Google Chrome team or like people who would take that really seriously; a lot of people working on the web who wanted to be just every bit as powerful as a native platform. So don't just assume that it can't.
55:28 Yeah, I totally agree, that whole way of thinking about the web is why I brought it up, because I think it's really cool. All right, two more questions before I let you go Ryan. If you are going to write some Python code, what editor do you open up?
55:41 I 'm very much a Vim user, specifically Vim 80 by 24 terminal window sort of you've got to work pretty hard to encourage me to make it any wider than that. I don't know if that's actually a productive way to get code written, I'm just so used to it, I can't go with anything else, but yeah.
56:03 Perfect. And then, there is 60 000+ excellent packages on PyPi, what are some that you think people should know about them, maybe they don't.
56:15 Interesting. So a friend of mine from the local Australian part of community Russell Keith-Magee, he kind of does a lot of stuff in Django, he has a interesting new project called Toga, which is kind of GUI library, right, he is working on native applications. But it's a GUI library with kind of all of the last however many years of experience writing Python under its belt, so you can do fun things like pip install toga, and it works, on whatever platform you happen to be on, you can get up and run in with your Google library. It's got things like support for IOS and Android UIs and stuff like that. So I think it's pretty neat, I haven't had a lot of excuse to play around with it but I've kind of checked it out out of interest, so if you are working in native GUI applications in Python, it's really worth checking out.
57:11 All right, excellent. I hadn't heard about that one so I'll check it out myself. Ryan, this is really excellent, congratulations on this project. I think the fact that you brought Python to the web in a way that executes faster than CPython in a lot of ways is really an accomplishment and maybe we'll solve this download speed thing and it will really take off, that would be great.
57:33 We'll see how it goes, it's been a lot of fun in any case, that counts for a lot.
57:37 Yeah, sure it does. Thanks for being on the show, talk to you later.
57:40 Thanks very much Michael.
This has been another episode of Talk Python To Me.
Today's guest was Ryan Kelly and this episode has been sponsored by Hired and CodeShip. Thank you guys for supporting the show!
Hired wants to help you find your next big thing. Visit hired.com/talkpythontome to get 5 or more offers with salary and equity right up front and a special listener signing bonus of $4,000 USD.
Codeship wants you to ALWAYS KEEP SHIPPING. Check them out at codeship.com and thank them on twitter via @codeship. Don't forget the discount code for listeners, it's easy: TALKPYTHON
You can find the links from the show at talkpython.fm/episodes/show/32
Be sure to subscribe to the show. Open your favorite podcatcher and search for Python. We should be right at the top. You can also find the iTunes and direct RSS feeds in the footer on the website.
Our theme music is Developers Developers Developers by Cory Smith, who goes by Smixx. You can hear the entire song on talkpython.fm.
This is your host, Michael Kennedy. Thanks for listening!
Smixx, take us out of here.