#32: PyPy.js - PyPy Python in Your Browser Transcript
00:00 Imagine a future where you're building a rich client-side web app.
00:03 You start by creating some backend services, maybe in Flask or Node, create an HTML page, you throw in a few divs and ULs,
00:10 and then you type script source equals main.py language equals Python.
00:15 That future might just be possible for the right type of applications with Ryan Kelly's PyPy.js project.
00:22 This is Talk Python to Me with guest Ryan Kelly.
00:27 Show number 32 recorded Wednesday, September 30th, 2015.
00:54 I have many interests, sometimes conflates my creativity.
00:57 Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the ecosystem, and the personalities.
01:04 This is your host, Michael Kennedy.
01:06 Follow me on Twitter where I'm @mkennedy.
01:08 Keep up with the show and listen to past episodes at talkpython.fm and follow the show on Twitter via at Talk Python.
01:16 This episode is brought to you by Hired and Codeship.
01:19 Thank them for supporting the show on Twitter via at Hired underscore HQ
01:23 and at Codeship.
01:24 Hey, everyone.
01:26 Thanks so much for listening in.
01:28 No news today, so let me introduce Ryan and we'll get right to the interview.
01:31 Ryan is a software developer based in Melbourne, Australia.
01:36 Most of his days are spent coding in Python and JavaScript, commercially as an engineer at Mozilla,
01:41 as well as for a variety of open source projects.
01:44 He also maintains a strong interest in logic programming, mainly as a result of his doctoral thesis.
01:49 Ryan, welcome to the show.
01:52 Thanks for having me.
01:53 I'm super excited that you're here today.
01:55 We're going to talk about Python, but in a place that you typically don't find it,
01:59 in the browser, right?
02:00 Yep.
02:02 Yeah, there's a lot of cool projects out there, and I'm a huge fan of the one that you've been working on.
02:07 Before we get to that, though, let's talk about how you got into programming.
02:11 What's your story?
02:11 Sure.
02:12 So I think it was quite a while ago now, and I actually started programming in JavaScript in high school way back in the day
02:19 for a class, right?
02:21 I was never the kid that sort of always grew up with computers.
02:24 I very much just got into it for a school assignment and pretty much fell in love straight away.
02:30 You know, I just fell in love with the ability to have a thought and kind of capture that in some concrete form
02:37 and have it executed and have effects on the world.
02:39 It's pretty amazing.
02:40 And actually, that kind of subject changed my entire career path.
02:44 I'd always planned to go into the sciences, and I had sort of a half a semester of computer programming in high school
02:51 and changed my whole career trajectory into engineering and computer science.
02:54 I think a lot of us who are in programming had that experience where maybe we didn't think that we were programmers per se, right?
03:02 But then you get some experience where then you're like, wow, this is really amazing.
03:06 This is really way more rewarding than a lot of other stuff.
03:08 I had that experience in math.
03:10 I studied lots of math, and I'm like, but we don't build anything here.
03:13 Programming is so much more concrete but creative.
03:17 I love it.
03:18 Yeah, it's that beautiful combination of kind of creativity in the mix, right?
03:24 The discovering and creating is pretty cool.
03:27 Yeah, sure.
03:28 So how did you get to Python?
03:29 I was handed Python as a requirement for an internship I was doing in university.
03:37 I went to work for a company that was doing engineering simulations.
03:40 So I think like a lot of people, I sort of come to Python because it has really strong tools for doing data analysis and visualizations.
03:46 So that was in a kind of typical intern project kind of way.
03:52 It's kind of like, here is a relatively well-scoped project, and you're using this language, and off you go.
03:57 But I just found that it really fit my head in a way that a lot of other languages that I've been dabbling around with didn't.
04:04 It was just kind of super easy to get up and running and dive in, and I found that the more time I spent with it,
04:11 and the more I came to understand the language and find all of these more and more interesting corners of it,
04:16 it just kind of grew from there.
04:17 And sort of since from that point, it's always been my kind of go-to language for side projects or projects where I'm not kind of locked into a language for other reasons.
04:29 Yeah, I think Python has this rare combination of being very capable and yet very simple.
04:36 There's a lot of capable languages, and there's a lot of simple languages, but they don't often intersect.
04:41 So that's great.
04:43 I've worked in some interesting languages like Prologue, and there's a language called Mozart, which is like a logic programming language.
04:49 And they're incredibly powerful, but yeah, they don't have that just clarity that Python has.
04:55 So before we get to talk about your project, you work at Mozilla, right?
05:00 That's right.
05:01 I'm a huge fan of Mozilla.
05:03 Firefox is definitely my browser.
05:06 Cool. Good to hear.
05:07 Yeah, I try to spread the word.
05:09 What do you do there?
05:09 I used to work with the cloud services team.
05:12 We're not an independent team anymore.
05:13 So when I first started out, I was working on the web servers behind Firefox Sync.
05:18 So doing sort of data storage and RESTful JSON APIs.
05:23 They're all Python-based servers.
05:27 So it's pretty standard kind of Python backend web gig.
05:32 Through a series of kind of mergers and reorgs and so forth, I actually wound up on a project that's operating in Node.js.
05:40 So my time these days is spent on Firefox accounts, which is the login system for Sync and for all of the new kind of cloud-based services that Mozilla is doing.
05:49 And it's a 100% JavaScript shop, that team.
05:53 So it's an interesting change of pace.
05:56 But it does leave me kind of itching to get more involved in Python stuff on the side.
06:00 Yeah, that's really interesting.
06:02 I think that's a good lead into your topic because it's like Python and JavaScript, those two worlds colliding, right?
06:10 Right.
06:12 So maybe at a really high level, we could just talk about your project, PyPyJS, and then we could talk a little more specifically about it.
06:20 Sure.
06:22 So at a super high level, I like to describe it as an experiment in building a fast and compliant Python environment for the web.
06:31 So concretely, it means like I want a Python interpreter that will run on top of JavaScript.
06:37 So anywhere you would go that you would want to do something in JavaScript, you should be able to take Python to that platform as a first-class citizen.
06:45 And obviously, a big place where JavaScript shows up is in the browser.
06:49 And the browser is just dominated by JavaScript.
06:52 There's really not a lot of other games in town if you want to do scripting in the browser.
06:56 But I'm also kind of interested in how it might fit on the server side in Node.js or other JavaScript frameworks as well.
07:02 But basically, being able to take other languages such as Python and put them anywhere where JavaScript is currently claiming as its home turf.
07:10 Yeah, that's great.
07:11 I mean, there's definitely been people talking how JavaScript is becoming the new assembly language of the web.
07:16 And we'll get into that.
07:17 So the way that I heard about your project was you gave a really excellent presentation at PyCon 2015.
07:24 Oh, thank you.
07:26 Yeah, yeah, definitely.
07:27 What was the title of it?
07:28 I forgot.
07:29 PyPy.js.
07:31 What, how, why?
07:32 I think from memory.
07:33 Yeah, that's perfect.
07:35 Yeah, I think you're right.
07:35 And it's on the YouTube channel for PyCon US 2015.
07:39 So I'll be sure to link to that in the show notes.
07:42 One of the ways you opened your talk was you talked about how Mozilla loves the web.
07:47 And not just the technology of it, but sort of the whole idea and the culture of it.
07:51 Can you maybe talk about that a bit?
07:53 Sure.
07:54 Sure.
07:54 So we have this saying at Mozilla.
07:57 And this was sort of one of the things that really inspired me to get started on this project.
08:00 We like to say like the web is the platform.
08:03 Well, this is kind of the world we want to live in is where the web is the platform.
08:08 And so the web, not necessarily from a technology standpoint, but from a kind of computing platform standpoint, is pretty unique and pretty amazing.
08:17 It's a platform that doesn't have any kind of all-powerful gatekeepers.
08:23 It's a platform where anyone can kind of show up and start participating.
08:28 You can publish stuff on the web without having to be locked into a particular hardware platform or a particular set of tools.
08:34 You can show up and start consuming stuff from the web without any of the similar sets of restrictions or requirements.
08:43 And so at Mozilla, we kind of see the web as a really powerful tool for empowerment and participation in the global kind of information economy.
08:55 Of course, the web, you know, from a social standpoint, that's all very well.
09:01 But when you get right down to the technology of the web, it doesn't necessarily tick all of those boxes, right?
09:07 In a sense, the technology stack of the web is a little bit kind of restrictive.
09:11 It's all kind of JavaScript and HTML in the browser.
09:13 There's kind of a lot of nice sociological aspects of the web that are really unique and really valuable.
09:21 And there are some technical aspects of the web that are not always to everyone's liking.
09:25 So that's an interesting platform in that respect.
09:27 It really is.
09:29 You know, you could have sold me on this idea with that statement in 2005, no problem.
09:37 But I think it's even more relevant now because we all have these app platforms and these proprietary APIs, you know, iOS, Android, OS X.
09:48 There's just more and more walled gardens and proprietary stuff.
09:53 Walled gardens and app stores.
09:55 Yes, absolutely.
09:56 And there's, you know, good financial reasons for that, right?
09:58 Absolutely.
09:59 And not just financial reasons.
10:01 Like curated content has a lot of user value and security value and stuff like that.
10:06 So the web has not completely undeserved reputation as a little bit of a security badlands because you don't know whose code you're running half the time.
10:14 You just could have got to trust that the browser is going to do the right thing for you.
10:17 That's right.
10:18 And that's, I think, partly why the JavaScript component of the web is so crucial because if it involves Flash or ActiveX or some other, you know, high privileged C-based plugin, it's not the web.
10:33 Not really.
10:34 Absolutely.
10:34 And you can't really trust it, right?
10:35 Absolutely.
10:35 And so your mission to bring things like Python to the web have to involve JavaScript somehow, right?
10:41 Right.
10:43 And I think there's been a long history and pretty much since the web has been a thing of trying to bring more kind of native platform functionality to the web.
10:53 You know, you mentioned Flash.
10:54 They've had, you know, ActiveX or Java applets, you know, way back in the day.
10:59 And the web has a really long history of trying to compete with native platforms by bringing native platform technologies kind of into the web by expanding the scope of the technology stack of the web.
11:14 As, you know, one after another have been kind of failures.
11:18 They fail to stick for any significant length of time.
11:23 And a lot of the time it's because of aspects like that security, right?
11:25 You're just kind of opening up too many holes, too many opportunities for things to go wrong.
11:29 Whereas if you take kind of JavaScript as your base level, then you can build on this sandbox that's had 20-odd years of, you know, figuring out how to get that right and build that model correctly.
11:42 So if you take that as your foundation, you kind of get a lot of the good security stuff and the lessons learned from the web for free.
11:48 Yeah, I totally agree.
11:50 And it's also worth noting the birthplace of JavaScript is Mozilla, right?
11:54 Well, it wasn't Mozilla back then.
11:56 But yeah, sort of the heritage of JavaScript sort of comes from the same place as Mozilla.
12:02 Yeah, absolutely.
12:03 Yeah, absolutely.
12:03 So when I think about JavaScript frameworks, there's the kind of more lightweight ones where it's, I'm writing, I'm taking some JavaScript API and I'm writing some more JavaScript code to write maybe a single page application.
12:20 So I'm thinking of like Angular, you know, those types of things, jQuery, so on.
12:26 And then at the other end, there's an idea of bringing more stuff into the JavaScript world using the concept of something called asm.js.
12:38 Can you speak to that a little bit?
12:40 So asm.js is a funny beast.
12:45 It's sort of this tiny little subset of JavaScript, which if you look at it in the right light and you kind of suspend disbelief for long enough,
13:00 inside of JavaScript are the semantics of a 32-bit CPU, essentially.
13:09 So JavaScript has, for what is a high-level language, JavaScript has a surprising number of kind of really low-level features.
13:17 Like it's got 32-bit bitwise integer operators and things like this.
13:24 Asm.js basically came out of an attempt by a very smart fellow named Alonza Kai to compile C code to the web.
13:33 And through a series of kind of experimenting with different ways of doing that,
13:38 came to realize that there was this subset of JavaScript that you could target that implemented the semantics of the machine more or less directly,
13:46 that you could then take C code and transliterate into this subset called asm.js.
13:52 And because of the kind of browser wars and the JavaScript performance wars that had been going on up to that time,
13:59 it also happened that that stuff would run pretty fast.
14:02 So he likes to describe it as discovering a kind of low-level 32-bit assembly language hidden inside JavaScript,
14:10 and I think that's pretty apt.
14:11 Very cool.
14:12 Have you seen the video or the PyCon presentation, Birth and Death of JavaScript by Gary Bernhardt?
14:19 I was present in the audience for that talk, and I loved it.
14:22 That was an amazing talk.
14:24 Those of you guys out there listening who haven't seen this, I'll put it in the links.
14:28 And I've referenced it before on the show.
14:30 But he did a really good job of showing off Asm.js and basically bringing anything that can be written in C to the web.
14:39 And one of those was like a pretty high-end video game like Quake or something like this, right?
14:46 They're doing sort of more – within half the speed of Native, I think they usually get these things running.
14:53 It's pretty amazing.
14:54 Yeah, very, very amazing.
14:56 And if you say high-end game like Quake, but I sort of sense that presentation has gone past,
15:01 I think they actually have been launching with even more kind of – the very latest and greatest gaming frameworks are starting to ship support for generating Asm.js JavaScript natively.
15:12 That's really amazing.
15:14 Okay, so there's this idea of we can take C code and we can compile it not to machine instructions,
15:19 but we can compile it to a special subset of JavaScript that then can be translated by the browsers to execute very fast.
15:28 Correct.
15:28 So how does this relate to your project, PyPy.js?
15:31 The PyPy.js is sort of a coming together of what to me are two amazing feats of engineering, right?
15:38 And one of them was Asm.js and Emscripten and this whole idea that you can treat the web more or less like a compile target,
15:46 as if it were a native CPU.
15:48 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:55 That's right.
15:56 That was show 21.
15:58 And PyPy, the interpreter, does some really amazing stuff.
16:01 It's incredible.
16:02 So one of the things that I think actually was talked about a little bit in that episode,
16:08 but one of the things I really like about PyPy is they weren't just focused on writing a really fast Python interpreter.
16:15 They were focused on creating a platform for experimenting with interpreters.
16:21 So it seemed to me the perfect kind of opportunity to learn more about both of these projects.
16:29 I'll learn more about PyPy.
16:30 I'll learn more about Emscripten and Asm.js.
16:33 Because PyPy is structured in such a way to make it really easy to dive in and kind of change bits in and out and play around with it,
16:40 I had this idea that I could get in there and like, well, I'll just find the just-in-time compiler backend inside PyPy,
16:48 and we'll just change it to emit Asm.js instead of, you know, x86 or ARM assembly,
16:54 which in a lot of projects would be kind of a terrifying proposition.
16:58 But because of the amount of kind of just good abstractions and so forth that are inside PyPy,
17:04 it actually was quite approachable as a problem.
17:08 So the coming together basically looks like the PyPy interpreter toolchain run through the Emscripten compiler toolchain
17:18 so that you get a version of it that is compiled to JavaScript.
17:22 And then at runtime, it uses the PyPy just-in-time compiler infrastructure
17:28 to take your Python code that you're running and spit out Asm.js at runtime,
17:34 in the same way that a native PyPy interpreter would spit out kind of specialized native code for your application.
17:39 So very much treating Asm.js as if it were just another dialect of some assembly language for a machine.
17:46 That's so amazing.
17:46 How long did it take you to get a proof of concept that was actually doing something?
17:51 I think my very first proof of concept without the just-in-time compiler part came together pretty quickly.
17:58 I lost maybe two weeks trying to figure out that Emscripten was actually assigning file descriptors
18:07 at different numbers than they usually are in Unix.
18:09 So like standard in is usually file descriptor zero, standard out is usually file descriptor one.
18:16 And it was giving them different numbers because it had never mattered before.
18:18 But PyPy really didn't like it.
18:20 So there are a few kind of just like toolchain compatibility problems like that.
18:24 But sort of once I got that figured out, right, is sort of just compile it as if you were running it through a cross compiler
18:32 and you get it up and running pretty quickly.
18:34 The JIT backend, I probably worked on, on and off for the better part of a year.
18:39 I conceived this scheme at the end of PyCon Australia probably three years ago.
18:45 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.
18:58 And in your mind, that had to sort of meet three criteria, compatibility, performance, and webbishness.
19:04 Can you talk about that?
19:06 I wish I'd found a better word for that.
19:07 I think that's the official word, yeah.
19:10 Yeah.
19:12 So this is not the first time people have tried to do Python-y stuff on the web.
19:17 I think I even said in the talk it probably won't be the last.
19:21 But it's one of those classic cases that you get in software a lot of a triangle where the three goals are kind of more or less opposed to each other.
19:31 So you've had languages that compile to JavaScript.
19:35 That's a thing that we know how to do.
19:36 And we know how to do that relatively fast.
19:40 As long as your language semantically maps to JavaScript pretty well.
19:46 Python doesn't.
19:47 So in Python, you have big ints by default.
19:51 You have a variety of checks built into your arithmetic operators and a few things like that.
19:58 So the semantics of Python are actually quite different to the semantics of JavaScript, even though they look very similar.
20:05 On the one hand, it's easy to make something go fast in JavaScript.
20:08 If you're not too far from the semantics of JavaScript.
20:11 On the other hand, we know how to compile languages from one to the other, right?
20:16 It's sort of a Turing completeness argument.
20:18 So if we wanted to get a really compliant Python interpreter, you know, one that implements all of the edge cases of CPython up and running on a different platform, you know, it's not implausible that we can get that up and running.
20:34 So it's interesting to see how fast we can do it.
20:36 So there's kind of two relatively opposed goals there, right?
20:41 Being fast and being – I like to say being Python, right?
20:46 But doing all of the things that Python does, not kind of looking a bit like Python, but having JavaScript's number model and things like that.
20:53 Right.
20:53 Exactly.
20:53 There's all these – you know, when you talk to people about JavaScript, they're like, oh, there's all these JavaScript gotchas you have to be on the lookout for.
21:01 I don't typically hear people go, look out for all the Python gotchas because they're lurking everywhere, right?
21:06 Right.
21:06 Python's usually got your back.
21:19 This episode is brought to you by Hired.
21:22 Hired is a two-sided, curated marketplace that connects the world's knowledge workers to the best opportunities.
21:28 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.
21:37 Typically, candidates receive five or more offers in just the first week, and there are no obligations ever.
21:44 Sounds pretty awesome, doesn't it?
21:46 Well, did I mention there's a signing bonus?
21:48 Everyone who accepts a job from Hired gets a $2,000 signing bonus, and as Talk Python listeners, it gets way sweeter.
21:56 Use the link Hired.com slash Talk Python to me, and Hired will double the signing bonus to $4,000.
22:04 Opportunity's knocking.
22:06 Visit Hired.com slash Talk Python to me and answer the call.
22:09 It's usually got your back.
22:20 That's right.
22:20 And so you can't just, for example, translate floats in Python directly over necessarily to just run as JavaScript or numbers, especially integers, like you say, over to JavaScript numbers.
22:33 So there's all that.
22:34 That's the compatibility bit, right?
22:36 Right.
22:37 So, yeah, that's the compatibility aspect.
22:39 And things like parts of the standard library as well.
22:42 You know, do you have all of a full implementation of the sys module, including get frame and kind of the debugger and all of these things?
22:52 And it's interesting.
22:54 It's sort of like, well, I don't really use those things that often.
22:57 You know, I don't really depend on integer overflows escalating to big ints by default that often.
23:05 Or, you know, I don't use sys get frame that often.
23:07 But it's interesting.
23:08 But it's interesting.
23:09 As soon as you start trying to run, like, whole programs on Python, like, you'll find that, oh, you use some library somewhere that uses some library that happens to use one of those things, you know, in some corner of its API.
23:23 So even though they seem like edge cases, they're often not at a whole program level.
23:28 Right.
23:29 They're not necessarily edge cases for small, simple things.
23:32 But if you're going to really write major apps there, then all of a sudden those become things you have to worry about, right?
23:37 Right.
23:38 And something I'm very interested in is less about kind of writing Greenfield's Python code for the web.
23:43 Because, you know, personally, I am not that unhappy writing JavaScript.
23:47 I'm interested in taking Python code that you've written and putting it on the web without having to do a whole lot of work.
23:54 And the compatibility aspect really is really important for things like that.
23:57 Right.
23:59 Like script source equals some file dot py.
24:02 Something like this, right?
24:03 Right.
24:04 Well, so, something like that.
24:08 Yeah.
24:09 But it would be, you know, taking something that you've already written and being able to put it on the web and make use of all of the fun distribution aspects of the web without having to do a whole bunch of busy work to make it run in JavaScript.
24:20 Right.
24:21 Absolutely.
24:21 So it sounds to me like pypy.js completely nails the compatibility part because it's effectively PyPy.
24:29 Is that right?
24:30 Correct.
24:31 So the fun thing about basing this on PyPy is we essentially get the compatibility part for free because they put an amazing amount of work into being a really, really compatible with the Python language reference, cPython.
24:43 And then you get to the performance.
24:44 And performance has multiple aspects.
24:47 All right.
24:48 One is I've got my code loaded up.
24:50 And now I can run this and it's doing XYZ iterations per second with such and such amount of latency.
24:57 The other part of it is I visit the web page and then it responds.
25:04 Right.
25:05 Yes.
25:05 Maybe we could talk about those a bit.
25:08 Absolutely.
25:09 PyPy being interpreted with a just-in-time compiler generally targets kind of steady state performance of your application.
25:19 So, you know, you load some code and you run it for a while and the JIT has a chance to kick in and generate a specialized code and you get very nice kind of steady state performance for the code that you're running.
25:29 And I think, again, the combination of PyPy and Asm.js means we can kind of get a lot of that more or less, I don't want to say for free, but, you know, easily in a JavaScript environment.
25:43 What we really don't get and what is actually really important on the web, as you say, is that kind of initial startup experience.
25:51 Like the time between hitting a web page and being able to interact with it is even more critical on the web than it is in sort of places where you'd normally find Python.
26:05 And PyPy.js, realistically, right now does a pretty terrible job of it.
26:10 It's only so fast you can start interacting with the page and you've got to load sort of megabytes worth of JavaScript to even start running your code.
26:17 Right.
26:18 And so right now, if you look, I think, you know, you have a really great page, arewepythonyet.com, that talks about a lot of cool stuff.
26:25 We can get to that.
26:26 But on there you have the download size, both, you know, off of disk and sort of maybe on the wire, the GZIP representation on the wire.
26:35 And on disk, it's like it was a little higher, but you guys have gotten down to 15 megabytes, right?
26:41 Yep.
26:41 And what is that, like five on the wire?
26:44 Yeah, I guess down to comfortably on a single digits on the wire.
26:47 I think five is probably about right.
26:50 Which for a native application is not terrible.
26:55 Like that's kind of in the ballpark.
26:57 But for stuff that you have to load up in order to interact with a web page, it's not great.
27:01 Yeah.
27:02 Typically, we talk about minification of our JavaScript and it's smaller, usually smaller than five megs.
27:08 Yes.
27:09 Usually not measured in megabytes, let's be quite frank about it.
27:13 That's right.
27:14 That's huge.
27:16 What is that, 100K?
27:17 No, no, that's 20 megs.
27:18 But, you know, there are potential solutions, right?
27:24 I mean, there are CDNs, extreme caching.
27:28 Right.
27:29 Could alleviate this somewhat, right?
27:32 The core runtime parts could somehow be sort of shared across sites.
27:37 Indeed.
27:38 I think there's actually still a lot of low-hanging fruit in that size, right?
27:43 So that size includes, for example, an entire Unicode character database, which is built into the interpreter in PyPy.
27:52 It includes all of the standard library modules that are built into the interpreter, whether you're going to use them or not, and things like that.
27:59 So there is definitely some scope for making that smaller.
28:02 And I've made more minimal builds of it that are several megabytes smaller.
28:09 But I don't think it's ever going to get down to, you know, tens of kilobytes in size.
28:14 This is pretty unrealistic.
28:15 If you go and download CPython from python.org, compressed, that's like 22, 23 megabytes, right?
28:25 And so, you know, if you're going to ship the whole runtime, the implementation, the PyPy implementation, that's kind of a lower bound in some way.
28:32 Exactly.
28:34 But that's not always a problem.
28:38 You know, if you look at this as a way to write all of your kind of interactive website scripting in Python instead of JavaScript,
28:46 like you were saying, kind of script lang equals text Python, that's a tremendous amount of overhead to pay before you can do any of the interactivity on your site.
28:56 But if you're doing something like shipping a kind of more appy experience that you've built in Python,
29:03 kind of bootstrapping into, in the same way that you might if you're loading up a game on the web
29:08 or like some sort of more heavyweight application, it's less of a big deal.
29:12 So, and, you know, the games that are compiled for the web within script and have this problem as well, right?
29:18 You want to get into the game and start playing it.
29:20 You've got to download many more megabytes of like image assets and compiled code and all this sort of stuff.
29:26 But it's okay for that use case.
29:29 And I think that's sort of the point where we're at with the project now where the people that are sort of really showing an interest in starting to use it
29:36 are cases where that's going to be less and less of a concern, where you're okay to kind of wait for a few seconds while you're bootstrapping into a fairly elaborate experience.
29:47 Right.
29:47 And like I said, once you get that loaded up the first time, you can cache it.
29:51 So if you're able to wait five seconds or whatever it takes to download that, then, you know, maybe it's possible.
29:58 So games are obviously one concept here.
30:02 Maybe if you're 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.
30:09 Right.
30:11 So I had some preliminary kind of interactions with the Jupyter and IPython people trying to get this plugged in.
30:27 And in a sense, it actually went really well.
30:30 They've got a really excellent infrastructure for plugging in different language backends and different, you know,
30:35 they can do Ruby or whatever plugged into their infrastructure.
30:40 So that, in a sense, kind of works.
30:42 Like, hey, you can plug in, plug Pypy.js and run this completely client side.
30:46 Of course, then, what that's missing is all of the fun libraries that you might want to use with that.
30:51 So if you want to do scientific Python on the web, scientific kind of programming on the web in Python,
30:56 you're going to want things like NumPy and sort of all of the analysis libraries that typically go along with that.
31:03 So I'm still interested in kind of pushing ahead and seeing where we can go with that.
31:09 But I think it becomes more of a library problem at that point, making sure you can actually ship that,
31:15 all of the details of that experience that people would expect and not just the Python interpreter itself.
31:20 The Python interpreter itself is actually probably the easiest of the bits, right?
31:25 Because then you've got to get NumPy and SciPy and Scikit-learn, and a lot of those have C extensions,
31:31 which then you've got to get into Asm.js again.
31:34 Right.
31:34 There's a lot of nuances that people building those libraries have never thought of, right?
31:39 Exactly.
31:40 And so in theory, that's all possible, right?
31:44 It's all the same principle of we've got code for a native platform where we can retarget it for the web.
31:49 But it's never quite that straightforward in practice.
31:52 Do you want to talk about arewepythonyet.com a bit?
31:57 Sure.
31:57 Yeah.
31:59 So what was the idea?
32:01 You said that was inspired by some sort of performance metrics at Mozilla historically.
32:07 The domain name in particular is a little kind of inside joke at Mozilla, right?
32:13 When the browser performance wars were really heating up, folks that were working on JavaScript performance at Mozilla needed a place to put their public JavaScript benchmarks.
32:24 And so they created this site called arewepastyet.com, which you could go to and just kind of look at all of the different JavaScript benchmarks that were running in the different engines.
32:33 And it kind of became a little bit of a thing at Mozilla.
32:35 So when people were talking about, oh, Firefox is a real memory hog and we need to do something about the memory usage of Firefox, you know, they started up a metrics tracking site called areweslimyet.com.
32:46 We were starting to really measure our community contributions and figure out, you know, how many contributors we're getting from different parts of the world and how big the community is growing.
32:55 Like they set up a metrics tracking website called arewemillionyet.com.
33:00 And sort of 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 up somewhere for everyone to see.
33:09 The other folks that are really keen on, you know, doing public performance measurements are the PyPy team.
33:15 So the benchmarks that are on arewepythonyet.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.
33:26 But yeah, sort of both places, I guess, have a really strong history of being really upfront and public about all of their performance metrics tracking.
33:37 I think it's a wonderful philosophy to try and follow in the footsteps of.
33:40 Yeah, that's great.
33:42 And you go there and you can really quickly see where the performance is really good and where it might lag behind.
33:48 And one of the things I thought was really interesting is there are plenty of places where PyPy.js is literally faster than CPython.
33:58 Yep.
33:59 All of that magic, of course, is due to the PyPy JIT.
34:04 And if you change the comparison to compare it to a native PyPy, of course, it's going to be uniformly slower.
34:09 But yeah, I was pretty amazed.
34:12 That's sort of one of the challenges I set myself when I was starting out on this little experiment was to say, look, you know, is the combination of Asm.js, you know, being almost as fast as a native platform and PyPy being kind of consistently faster than CPython.
34:29 Can that in combination mean we can actually run Python benchmarks in the web faster than your standard Python interpreter?
34:36 And it's pretty astonishing to find out that that is, in fact, the case.
34:44 This episode is brought to you by CodeShip.
34:57 CodeShip has launched organizations, create teams, set permissions for specific team members, and improve collaboration in your continuous delivery workflow.
35:07 Maintain centralized control over your organization's projects and teams with CodeShip's new organizations plan.
35:12 And as Talk Python listeners, you can save 20% off any premium plan for the next three months.
35:18 Just use the code TALKPYTHON, all caps, no spaces.
35:21 Check them out at CodeShip.com and tell them thanks for supporting the show on Twitter where they're at CodeShip.
35:33 Yeah, I was, when I pulled this up, I was like, all right, let's see how many times slower it is.
35:39 Is it like something we could live with because it's going to run in the browser?
35:42 And I was like, wow, okay, that's really cool.
35:44 It's also fun to click off the D8 interpreter in those comparisons and get just the SpiderMonkey engine.
35:53 It'd get a little bit more times faster than CPython as well.
35:56 That's awesome.
35:57 And of course, D8 is Chrome and SpiderMonkey is Firefox, right?
36:02 V8 JavaScript engine, yes.
36:03 Same one that runs Node.js, right?
36:06 So very interesting.
36:07 So the performance story is really, really good on the execution side.
36:13 But then you also have the stuff about sort of the startup and the download size and so on.
36:18 Right.
36:19 So there's no point, you know, trying to hide any of that stuff.
36:22 There's a whole tab there about startup overhead.
36:24 And it does indeed measure the download size in megabytes.
36:27 And you can, you know, it's even got a little feature there.
36:30 You can actually click to just test how long it'd take to load up on your machine.
36:34 What's interesting here actually is the download size is one thing.
36:40 Like that's kind of understood and easy to grasp.
36:43 But there's also a graph of the time it takes.
36:45 Like once you've downloaded that, how long does it take for the JavaScript engine to actually kind of initialize this interpreter?
36:52 And that actually is on the order of a second or two just by itself, right?
36:56 Kind of taking all of that JavaScript code and parsing it and loading it up into the browser is actually, you know, makes the browser work really hard.
37:04 Yeah, it's a large quantity of JavaScript that you can understand, right?
37:09 So, you know, you work at Mozilla.
37:12 Maybe you can pull some strings.
37:13 Is it, would it be possible to take projects like this, like Asm.js and PyPy.js and have them sort of certain versions shipped with browsers?
37:26 So like when I load up Firefox and I hit a page and it says, give me PyPy.js, it goes, we already have that downloaded.
37:34 Let's go.
37:34 I'd love to think I could pull those strings.
37:37 I don't know if I really have that power.
37:39 But 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.
37:57 So, you know, we could kind of put this in the browser and say, yeah, like, you know, we want to treat Python as a first class language and we're going to special case it in the browser and get a really good experience for Firefox users.
38:10 But the individual market share of us or any other browser who tried to do that is probably not sufficient to, for people writing websites to be able to depend on it, right?
38:21 Yeah, absolutely.
38:22 And the most important use case of that would be on mobile.
38:26 And then that's an even harder sell.
38:28 Absolutely.
38:28 Absolutely.
38:30 What's really interesting and sort of segueing out of that a little bit, what you really need in order for something like this to kind of take the next step and to get over some of these kind of fundamental problems of code size or load time or whatever is, you know, if you can't find a way to hack around that in JavaScript, which for some of these things we really can't.
38:51 You kind of need all of the browser vendors to agree on a way forward and sort of everyone's got to ship something better together.
39:00 And one of the amazing things that's happened coming out of Asm.js and experiments like the Games initiative that have kind of proven that that's a really powerful thing is you're actually seeing all of the browser vendors sort of getting together and talking about, well, like, what's next after Asm.js?
39:19 Like, how can we make this better?
39:21 How can we really commit to this as the web rather than any particular browser platform?
39:27 That's really, I mean, that's the way the web works, right?
39:29 That's the way the web is successful anyway.
39:31 Like you said, people have tried to jam their way through, you know, like, IE6 type stuff that happened back in those days, but that's not really what sticks.
39:41 You've got to have a good story for getting from where the web is to where you want the web to be.
39:46 And Asm.js kind of really came in and provided that.
39:50 It's like, all right, we want to treat the web as a compilation target.
39:53 And here's a pretty okay way of doing it.
39:56 All right.
39:56 You know, we can get to that point.
39:58 So now you've got impetus to actually make that better.
40:04 Yeah, a foundational idea to start from that everybody can start to come from.
40:08 Right, exactly.
40:09 You know, people had traditionally talked about JavaScript as the assembly language of the web, sort of conceptually, but Asm.js is kind of making that concrete in a very real way.
40:20 The name of the kind of project that's spinning up out of that discussion is called WebAssembly.
40:26 And it's very much targeted at being like, here's an actual assembly language for the web, right?
40:31 It's kind of like, take that idea that Asm.js proved is plausible, you know, doing this assembly language on top of the semantics of JavaScript, but outside of the limitations of necessarily, you know, 100% backwards compatibility with JavaScript.
40:47 So it's gone from kind of like, yeah, this should be the assembly language of the web and kind of like, this is what it looks like, to suddenly taking that idea really seriously.
40:56 Yeah, the future is going to be super interesting when that sort of takes hold.
41:01 Absolutely.
41:02 And I think, you know, a lot of these problems, like the load time of the JavaScript and the download size, like they'll get better for free when that technology starts to kick in.
41:12 They won't go away, but they'll get better.
41:14 Right.
41:15 And a lot of the stuff that you sort of shipped from your site that would have been JS files or whatever are now binary, right?
41:21 In that spec?
41:22 Right.
41:23 Right, exactly.
41:23 So Python 2 or Python 3?
41:27 Currently Python 2.
41:29 Mostly by default.
41:31 But that describes me as well as this project.
41:35 I'm one of the laggards.
41:37 I'm sort of slowly coming to the realization that I'm falling behind and that I still use Python 2 by default everywhere.
41:45 That said, one of the neat things about this, right, is the PyPy team are working really hard on their Python 3 compatibility.
41:52 And so it's a pretty straightforward prospect to kind of ride along the coattails of that work and ship Python 3 in the browser just as easily as you can ship Python 2 on top of this technology stack.
42:03 Yeah.
42:03 That's great because you're just taking literally the PyPy interpreter as it is and sending it through this tool chain.
42:12 Whatever support PyPy has for Python 3 more or less is the support you have for it, right?
42:17 Right, exactly.
42:18 It sort of just comes out the other end.
42:20 And that goes for all of the other languages that people are experimenting with on top of the PyPy tool chain as well.
42:26 Yeah.
42:27 I read an interesting article just this week talking about Python 2 versus Python 3.
42:31 And, you know, there's a lot of practical reasons that a lot of people are still doing Python 2.
42:35 And this article was called Planning an Early Death for Python 2.
42:39 And it had some really interesting ideas.
42:41 I'll be sure to link to it.
42:42 But a lot about the way, like, people culturally think and talk about Python.
42:47 They were attempting to change that there.
42:49 And I thought it was an interesting idea.
42:50 Anyway, I'll link to that for everyone.
42:51 Yeah, cool.
42:52 For what it's worth, I've really noticed a change in the community in the last year or two where it's kind of Python 3 is – it seems to have kind of broken through in a sense.
43:02 Like, people might look at you a little bit odd if you're not taking Python 3 seriously.
43:07 Or at least it's something I've noticed anyway.
43:10 Yeah, I've definitely noticed the same thing.
43:12 So are there notable deployments or places that we could go find that PyPyJS is being used yet?
43:20 Or is it too early for that?
43:22 What's the story around there?
43:23 I think it's broadly too early for that.
43:26 I mean, you can go to the PyPyJS website and muck around with it.
43:29 It's sort of an interesting project for me.
43:32 I was sort of in the position of doing a project that I don't really want to build anything with.
43:36 Like, the project itself is the point of it for me.
43:39 So I've been talking to a couple of different people who are interested in trying it out as part of an actual product.
43:46 In places where you might use something like IPython or sort of one of the other in-browser Python environments currently.
43:54 But I don't think any of those are live yet.
43:57 They've certainly – I've got people showing up and chipping into the project and trying it out and experimenting with using it in their stuff.
44:05 But I don't think anyone's quite put it into production just yet.
44:08 Right.
44:08 And if you want to check out the code, it's at github.com/PyPyJS.
44:12 So pretty easy to find, right?
44:16 Do you see maybe a use case in some of the more, like, offline app-ish HTML5 apps?
44:25 So I'm thinking, like, Firefox OS, like, PhoneGap-type platforms?
44:30 Absolutely.
44:31 So that's one of the places where the startup overhead of this whole infrastructure will be less of a problem.
44:38 Because you can list, you know, the files to be downloaded as, like, your app manifest.
44:42 And you kind of get better control over the caching and things like that.
44:46 So it probably makes more sense in that sort of contained experience of an app than it does as, you know, a bit of scripting on the open web somewhere.
44:55 Sure.
44:57 Yeah, that definitely seems like it.
44:58 What about Chrome OS?
44:59 To be honest, I haven't thought about it.
45:03 I'm not sure you're allowed to promote them, but, you know, those do have sort of prepackaged offline manifest type stuff, right?
45:09 So it seems potentially would be good.
45:12 And particularly as the web kind of comes to terms with that packaging of applications and more standards sort of start 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.
45:28 It's kind of like, oh, this is how we do packaged apps for the web.
45:30 And Python has a place in that ecosystem.
45:33 That would be a really great outcome.
45:34 That would be absolutely a great outcome.
45:36 There are other sort of Python in a browser type frameworks or attempts or projects.
45:44 And you listed something like at least nine in your talk.
45:47 You know, two that are pretty popular come to mind.
45:50 One is Sculpt.js.
45:51 I had Brad Miller on one of the earlier shows to talk about that.
45:55 And another was Brython.
45:56 And those seem more like, you know, script lang equals Python sort of type of frameworks.
46:04 But they make tradeoffs to make that possible.
46:06 Can you compare those a bit?
46:08 Exactly.
46:09 I'm not super familiar with Sculpt.
46:11 But I had a look at Brython in some detail.
46:14 And I'm actually quite a fan of the stuff they're doing.
46:17 I think they've selected an excellent set of tradeoffs.
46:20 It's a different set of tradeoffs to the ones that PyPy.js is interested in.
46:26 And the big tradeoff that they make in Brython to get good performance is the number model.
46:33 So if you do like a for loop, like, you know, for X in range one to 100, right, that will get turned more or less directly into a JavaScript loop over JavaScript numbers.
46:45 And for that use case, it's absolutely fine.
46:48 Like, JavaScript numbers will behave correctly.
46:51 But if you ever happen to get yourself, get your code into a situation where, you know, you're counting up a little too high or you're dividing by a number that you're accidentally dividing by zero or something like that, then you're not quite getting the semantics of Python's number model on top of Brython.
47:08 For the script kind of text equals Python use case, we're actually, like, writing new code.
47:17 You can write that code for Brython, and it's a really excellent set of tradeoffs.
47:21 Because you know to watch out for those things.
47:23 But if you were to take a, just, you know, get some Python code off the shelf and try and run it through, then, you know, you've got more chance of it's going to trip you up.
47:31 So, of course, what you get in return for making that tradeoff is you get a much better kind of startup experience, much lighter weight integration into the browser, a lot less JavaScript to load.
47:42 And in some cases, sort of a tighter integration with the browser and with the native DOM and stuff like that.
47:51 Right, because they can lean more heavily on JavaScript itself.
47:54 Correct.
47:55 So, from Brython's perspective, it's targeting JavaScript.
48:00 So, it can interact with JavaScript objects and this sort of thing.
48:04 From PyPyJS's perspective, it's kind of targeting this weird C-like platform that happens to run on JavaScript, but you can't really see.
48:15 It's difficult for it to see the native JavaScript objects and so forth in a sensible way.
48:19 You did show a way that you could interact with libraries such as jQuery and the DOM and so on.
48:25 Absolutely.
48:26 From PyPy.js, right?
48:27 Yes.
48:28 That works.
48:29 That actually works surprisingly well for what it is.
48:32 And the way to think about that is a lot more like C-types or CFFI.
48:39 Like, it's more like you're doing a C-binding to the objects in your JavaScript world than interacting with them directly.
48:47 And on top of that, you can build a nice little API that exposes them as Python objects.
48:51 But when you go to use that bridge between PyPyJS and the native JavaScript environment, you're going through basically indirecting through a C-API.
49:05 That makes it something of a challenge to do fast and to do things like cross-language reference cycles, for example.
49:14 You know, if you've got a Python object that refers to a JavaScript object that refers back to a Python object, it can get a bit weird.
49:21 But for a lot of stuff, it works surprisingly well.
49:25 Oh, yeah.
49:26 Because, you know, maybe you don't need super complicated interaction.
49:29 But, like, I'd like to grab something out of this text box and then display it over here in this, you know, select or whatever.
49:35 Yeah.
49:36 Yeah.
49:36 For things that are, you know, strings and things that are immutable or things that don't really have references back into Python, it's fine.
49:44 No dramas at all.
49:45 One thing that I was thinking about as I was thinking about your project was, you know, you're talking about taking Asm.js and focusing on that.
49:55 And compiling down to this subset.
49:56 And there are other projects that both describe Python sort of more fully and JavaScript more fully.
50:06 So, for example, TypeScript on the JavaScript side, which is like an optionally typed JavaScript type thing that AngularJS has adopted, right?
50:15 And then the type hints that are coming in Python 3.5.
50:19 Do any of those types of things help here or does it just not really matter?
50:23 I think the way this particular kind of collection of technologies operates is at far too low a level for those to make a difference.
50:32 I think it would be really interesting to try and do higher level correspondence between those two things.
50:40 But I think it would be a very different size and shape project.
50:44 Yeah, it's not something you could shoehorn in, is it?
50:46 Right.
50:47 No, not at all.
50:48 Yeah, for all of the fun of kind of having it eventually run on JavaScript, actually, the experience of building it feels a lot more like building something in C.
51:01 And the JavaScript kind of just appears as a platform underneath it.
51:04 Because you're using the same tool set that they use for C, like LLVM compilers and things like that, right?
51:10 Right, so classic compiler tool chain that just happens to spit out JavaScript at the other end.
51:15 Yeah, it's like saying, well, when I'm doing C++, how does stuff happening in machine language and assembly, you don't even think about it, right?
51:25 Right.
51:25 Same thing here, more or less?
51:26 Right.
51:26 Exactly.
51:28 Well, Ryan, we're kind of coming up near the end of the show.
51:30 Do you have maybe some call to actions for people out there?
51:34 I'm really interested in connecting with people who want to put this to concrete use.
51:40 I think what the project really needs now is kind of be driven by concrete use cases.
51:47 So it's past the point of like, oh, experiment with these fun technologies and see what's possible, right?
51:54 See how fast we can make it or things like that.
51:58 There's still ground to cover, but that's kind of the real experimental phase of that is more or less done.
52:07 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,
52:17 it really needs to make that jump into something that people actually would be happy to deploy and practice.
52:24 I need to talk to a couple of people who are doing like Python shells in the web for a variety of reasons who are interested in trying it out.
52:33 But I'd love to hear if people had a Python application that they thought would be really interesting to port 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?
52:49 If you've got something that you think, that'd be really great if I could just take this Python kind of application and port it to the web.
52:56 I'd love to just kind of talk through the possibilities.
52:59 I think that's, as much as anything, that's what the project needs right now.
53:03 People to come and try and put it to use and see what works and what doesn't and we'll fix the bits that don't.
53:09 A great call to action and that is what makes projects real, right?
53:12 When people use them and they have to hit all the little edge cases and sort of smooth it out.
53:18 So it's a real product, right?
53:20 Exactly right.
53:21 You sort of can't get away from the fact that you've got to download 10 mega JavaScript.
53:25 You can wave your hands and pretend that's not an issue when you're doing an experiment but not when you're doing a product.
53:31 Right, absolutely.
53:33 So another thing that I thought you had as kind of a final call to action in your talk was the concept of filing bugs against the web.
53:41 Do you want to maybe talk to that really quick because that's a cool Mozilla idea, I think.
53:45 I guess the driving force for this project for me is really that philosophy.
53:50 It's the idea that the web should be a first class computing platform.
53:54 And a lot of people kind of in the habit of thinking like, oh, the web can't do this.
54:00 Or I really want to do this on the web but it's not going to work because X, Y, and Z.
54:05 And it wasn't until I actually started working at Mozilla that it kind of occurred to me that actually, you know, the web is a really fluid medium.
54:14 There are a lot of people who really care deeply about the web being a really powerful platform.
54:20 And sort of invested in the web.
54:22 Not necessarily winning but competing with native platforms.
54:28 And it's a change in perspective, right?
54:30 So if 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 That's, there's one thing to say that another thing to put it into practice, right?
54:41 If you come into bugzilla.mizilla.org and you're like, bug, I can't run Python on the web.
54:46 Like we may not close it as invalid straight away.
54:50 But it's probably, you know, it would be Intel projects like this.
54:55 A big chunk of work.
54:57 I don't know.
54:59 I encourage people to expect more from the web.
55:01 It's actually getting more and more powerful as an application platform.
55:05 And if it's 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 will take that really seriously.
55:18 There are a lot of people working in the web who want it to be just every bit as powerful as a native platform.
55:24 So don't just assume that it can't.
55:27 Yeah, I totally agree.
55:29 That's, you know, that whole way of thinking about the web is why I brought it up because I think it's really cool.
55:33 All right, two more questions before I let you go, Ryan.
55:36 If you're going to write some Python code, what editor do you open up?
55:40 I'm very much a Vim user.
55:46 Specifically Vim in an 80 by 24 terminal window.
55:50 Sort of, you've got to work pretty hard to encourage me to make it any wider than that.
55:54 I don't know if that's actually a productive way to get code written or if I'm just so used to it that I can't cope with anything else.
56:00 But Vim all the way.
56:02 Perfect.
56:03 And then there's, you know, 60 plus thousand excellent packages out on PyPI.
56:10 What are some that you think people should know about that maybe they don't?
56:14 Interesting.
56:16 So a friend of mine from the local Australian Python community, Russell Keith McGee, who's a kind of does a lot of stuff in Django.
56:24 He has an interesting new project out called Toga, which is a kind of GUI library, right?
56:31 He's working on native applications.
56:33 But it's a GUI library with kind of all of the last however many years of experience writing Python under its belt.
56:43 So you can do fun things like pip install Toga, and it works on whatever platform you happen to be on.
56:48 And you can get up and running with your GUI library.
56:52 It's got things like support for iOS and Android UIs and stuff like that.
56:57 So I think it's pretty neat.
56:58 I haven't had a lot of excuse to play around with it, but I've kind of checked it out out of interest.
57:04 So if you're working in native GUI applications in Python, I think it's really worth checking out.
57:10 All right.
57:11 Excellent.
57:11 I hadn't heard about the one, so I'll check it out myself.
57:15 Ryan, this is really excellent.
57:16 Congratulations on this project.
57:18 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.
57:27 And maybe we'll solve this download speed thing, and it'll really take off.
57:31 That'd be great.
57:32 We'll see how we go.
57:33 It's been a lot of fun in any case, so that counts for a lot.
57:36 Yeah, it sure does.
57:38 Thanks for being on the show.
57:39 Talk to you later.
57:40 Thanks so much, Michael.
57:41 Bye.
57:45 This has been another episode of Talk Python to Me.
57:47 Today's guest was Ryan Kelly, and this episode has been sponsored by Hired and CodeShip.
57:51 Thank you guys for supporting the show.
57:53 Hired wants to help you find your next big thing.
57:56 Visit Hired.com slash Talk Python to Me to get five or more offers with salary and equity presented right up front,
58:03 and a special listener signing bonus of $4,000.
58:05 CodeShip wants you to always keep shipping.
58:08 Check them out at CodeShip.com and thank them on Twitter via at CodeShip.
58:13 Don't forget the discount code for listeners.
58:14 It's easy.
58:15 Talk Python.
58:16 All caps.
58:17 No spaces.
58:17 You can find the links from today's show at talkpython.fm/episodes slash show slash 32.
58:24 Be sure to subscribe to the show.
58:27 Open your favorite podcatcher and search for Python.
58:29 We should be right at the top.
58:31 You can also find the iTunes and direct RSS feeds in the footer of the website.
58:35 Our theme music is Developers, Developers, Developers by Corey Smith, who goes by Smix.
58:40 You can hear the entire song on talkpython.fm.
58:43 This is your host, Michael Kennedy.
58:45 Thank you for listening.
58:46 Smix, take us out of here.
58:48 I'm first developers.
59:04 I'm first developers.
59:06 I'm first developers.
59:07 I'm first developers.
59:09 First of all, first of all, first of all, first of all.