Learn Python with Talk Python's 270 hours of courses

#10: Bringing Python to the Masses with Hosting and DevOps at PythonAnywhere Transcript

Recorded on Tuesday, May 12, 2015.

00:00 It's time to obey the testing goat and fire up some Python in the browser.

00:04 This is Talk Python to Me, episode number 10, with guest Harry J.W. Percival, recorded

00:10 Tuesday, May 12, 2015.

00:12 Hello, and welcome to Talk Python to Me.

00:42 A weekly podcast on Python.

00:44 The language, the libraries, the ecosystem, and the personalities.

00:47 This is your host, Michael Kennedy.

00:49 Follow me on Twitter, where I'm @mkennedy, and keep up with the show and listen to past

00:54 episodes at talkpythontimmy.com.

00:56 This episode, we'll be talking to Harry Percival from Python Anywhere about hosting Python applications

01:02 and making Python available to the masses, as well as his book and mission, TDD in Python.

01:09 I'm thrilled to tell you that this episode is brought to you by Codeship.

01:13 Codeship is a platform for continuous integration and continuous delivery as a service.

01:18 I'll talk more about them later in the show.

01:20 Please take a moment to check them out at codeship.com or follow them on Twitter, where they're at Codeship.

01:25 This show is kind of special because I've traveled all the way from the west coast of the United

01:30 States to cheerio, London to meet with Harry in person.

01:33 Well, maybe I also came here for a conference in central London, which happens to be close to Python Anywhere's headquarters.

01:39 Either way, it was really fun to do an in-person interview with Harry.

01:43 Now, let's get to the show.

01:45 Harry, welcome to the show.

01:48 Hi, Michael.

01:49 Thanks for having me.

01:50 I'm excited about it.

01:50 This is really an amazing show.

01:53 It's the first one we're doing in person.

01:55 Right.

01:56 Okay.

01:56 All right.

01:57 Well, I hope I don't mess it up.

01:58 No, you definitely won't.

01:59 So I'm here in London.

02:01 I'm not normally in London.

02:02 I love this place, but I don't live here.

02:03 So it's kind of unique.

02:05 And I happen to be at a conference like a block away from your office where Python Anywhere is.

02:11 Right.

02:11 There you go.

02:12 And so why don't we get together and do this in person?

02:14 And here we are.

02:15 Fantastic.

02:16 All right.

02:17 So I really want to talk about Python Anywhere.

02:20 I want to talk about Obey the Testing Goat, all those types of things.

02:23 But let's just start at the beginning.

02:25 How did you get started in programming?

02:27 How did you get started in Python?

02:28 Sure.

02:28 I guess I started in programming when I was quite young, like a lot of people, maybe when

02:32 I was 10 years old, on various old bits of hardware from the, this is the sort of early

02:39 90s, maybe even the late 80s.

02:41 And I had like an Amstrad PCW green and black background, had like one of the early Olivetti

02:49 laptops.

02:50 And this thing had, it had not one, but two three and a half inch floppy drives.

02:55 Oh my gosh.

02:56 No hard disk at all.

02:57 And you could run, you could run MS-DOS on one and Microsoft Word or a really good copy

03:02 of Snake on another one.

03:04 And then at school we had them as well.

03:07 So I was programming in basic.

03:08 I had a few books from America.

03:11 And at school we had these things called Thompson TO7s.

03:14 I've never heard of that thing.

03:15 Yeah.

03:15 Okay.

03:16 So it's a, it's like a, it's a big ugly box thing that you plug into a television screen

03:20 and it's got these like rubber keys on and they go like boop when you press them.

03:25 You know, 10 going toot, doot, go to 20.

03:28 And we're programming basic.

03:31 And the cool thing with that actually was that they had, they had this thing called an input

03:35 pen, which was like this pen thing that you could press against the screen.

03:38 And it had some voodoo that then would be able to register an XY coordinate against where

03:42 it was on the TV screen.

03:43 I guess it was like calculating where the sort of raster had got to or something like that.

03:48 That's pretty cutting edge for it.

03:49 What year was this?

03:50 This is like 1992, I'm going to say.

03:53 Wow.

03:53 Right.

03:53 That predates Mozilla.

03:55 Well, I think those computers were already old then, to be fair.

03:57 And so, yeah, we would make like little drawing programs on them, which is really cool actually,

04:03 because if you watch kids programming these days on much more advanced computers,

04:06 they've got really cool things like Scratch.

04:07 They don't have to go through basic and go-tos.

04:09 But they did exactly.

04:11 I mean, you watch kids in schools doing this.

04:12 They do exactly what I did at that age, which as soon as you figure you can do some graphics

04:16 on the screen, you start making a paint program, you draw circles and squares and spirals and

04:20 things like this.

04:21 And so, yeah, yeah, that sort of thing.

04:23 I'm sure everyone's got a similar story.

04:25 That's awesome.

04:26 So that's basic.

04:28 How about Python?

04:29 Yeah.

04:30 So that was my origins, right?

04:32 I was on the right path.

04:33 And then somehow my life went wrong and I sort of went and studied economics and I got a job as a management consultant,

04:40 which was very tedious.

04:43 And I didn't really do any programming other than kind of overcomplicated Excel spreadsheets

04:48 until I was pretty much 30 years old.

04:51 And this is like 2008.

04:54 I took a sabbatical from my job, which turned out to be just me quitting, basically.

04:58 Go off and do a new degree and get a master's in computer science and just learn programming again

05:04 and kind of do it properly.

05:05 And then I went off and that's what I do now.

05:08 Nice.

05:09 Was it really refreshing to step away from science?

05:12 Yeah.

05:12 Well, management consulting is a lot of talk, not so much action.

05:18 Yeah.

05:18 Yeah.

05:19 I mean, so it's not for everyone, I think.

05:21 It wasn't for me.

05:22 And it was interesting in parts.

05:25 But I found myself, like, just if I looked at the part of the job that I enjoyed,

05:28 it was mostly just making an overcomplicated Excel spreadsheet and, you know,

05:32 like just a 25-line functions in Excel and, like, VBA to do things that were, like,

05:37 absolutely not required by the project that I thought were cool.

05:40 So, you know, there was a clear direction I should probably have been going.

05:44 You should have taken that clue.

05:45 You know, my programming experience is like that as well.

05:50 I kind of became an accidental programmer.

05:52 I was working on my PhD in math and was working on some Silicon Graphics,

05:56 like supercomputers, right?

05:57 And I remember after about a year of working on this project, it was this cool 3D simulator that I really enjoyed working on,

06:04 except when I got to the math parts.

06:06 And then after about six months of that, I'm like, you know, maybe I should take this as a clue that I should stop doing math and go do computers.

06:14 So very cool.

06:14 Nice to hear that.

06:15 Yeah.

06:16 So I know you because when I was looking for a place to host my website and get started,

06:21 I ran across Python Anywhere and I thought, wow, this is a super cool project you guys have.

06:27 It is amazing.

06:28 And so maybe you could tell me about that.

06:30 It's only moderately amazing.

06:33 It's pretty awesome.

06:35 Well, let's see.

06:36 So Python Anywhere is kind of, what is it?

06:40 It's a place where you can code Python in your browser.

06:45 And that could mean a lot of things.

06:47 And what it means for us eventually is like, I guess where we're really headed is to try and sort of be as Google Docs is to Microsoft Word.

06:55 Maybe we could try and be that to installing and running Python on your local computer.

07:00 Right.

07:01 So if you have Python that runs, you know, in the cloud with apologies for the buzzword, what can you do?

07:07 Well, so first of all, you don't have to install any software on your PC.

07:09 So you go along, you can come to our website and we'll give you a text editor, which is going to work.

07:15 And it's going to have syntax highlighting for Python and even maybe some error checking with the PyFlakes.

07:20 It's going to have a console just like you would have on your own computer and not just like a sort of line by line console, but like a real terminal emulator there.

07:27 So you can have tab completion.

07:28 You can run Vim or Emacs in it.

07:30 And we'll try and give you those tools that you're used to having on your PC in the cloud.

07:34 And what that gives you is the ability to kind of run things from anywhere.

07:39 And it gives you the ability to do more kind of collaboration things that are a bit harder to do on your own computer.

07:43 And then you can do some number crunching that maybe you can't do on your own computer because we can do maybe a little paralyzation for you.

07:51 And then finally, we can do web hosting.

07:52 So, you know, like we're already on servers.

07:55 It's that much, not much effort for us to then say, okay, well, we'll give your code some sort of public access to the Internet.

08:01 And so, you know, we end up having a lot of people just hosting websites on that.

08:05 Yeah, that's really cool.

08:06 Can you speak to, like, what percentage of users are doing what type of use case?

08:11 It's hard to tell, really.

08:13 Like, because we've got an awful lot of users of free users who come along.

08:18 And then, you know, like any website, there's some of them come and check it out and go, cool, and never come back.

08:22 And a lot of them will never talk to us.

08:24 So we're not too sure what they get up to.

08:26 But of the ones that pay us, an awful lot of them do use it for web hosting.

08:34 So, you know, we built this thing.

08:36 What it came out of was actually an online spreadsheet.

08:39 Okay.

08:40 So the company I work for is called Python Anywhere Now.

08:42 But when I joined it, it was called Resolver Systems.

08:44 And what they were building was a Pythonic spreadsheet.

08:49 So I mentioned I love spreadsheets earlier.

08:51 Yeah.

08:52 The reason I got this job is because I decided to do my thesis as part of my master's on spreadsheets.

08:57 That's amazing.

08:57 And what I thought I'd do is I'd phone out around a few companies that do spreadsheet software.

09:02 And, like, other than Microsoft, right, there's only, like, a very few of these, and they're small.

09:06 And I would just ask them, hey, I'm going to do a thesis all about spreadsheets because I'm crazy.

09:10 And probably if you guys love spreadsheets like I do, you want to sponsor me, right?

09:14 And there was one company stupid enough to say yes to that.

09:17 And that was Resolver Systems.

09:19 And that's how I ended up working there.

09:20 And they were making a Pythonic spreadsheet.

09:21 So, like, just imagine Excel, which works like Excel, except that when you want to script it, you get to use Python instead of using VBA.

09:29 That's a nice place to be, I would think.

09:31 It was really good fun and a great tool.

09:33 But, like, ultimately, if your pitch is you want to try and tell people to stop using Excel and use this other tool, it's a very high mountain to climb.

09:41 Yeah.

09:41 Even Google.

09:42 I think they're having some success with Google Docs.

09:44 But even for them and their reach, that's a hard story to tell.

09:47 Yeah.

09:47 So, like, for a small, like, five-person company out of London, it had a dedicated following of people who loved it because it was loads of fun.

09:55 But so that wasn't necessarily working.

09:58 So the first pivot was, like, let's take that online, right?

10:01 And let's build that tool.

10:02 Instead of having a desktop app, let's make it web-based and see whether people like that.

10:07 And they did.

10:07 And they liked the sort of number-crunching aspect.

10:09 But this was a sort of very, like, lean startup-y thing we were doing.

10:13 Let's reinvent this product online.

10:15 We did that sort of for three or four months.

10:16 I tried to gather a lot of user feedback.

10:18 And what people were coming back to us and saying is, you know, like, the coolest thing about this isn't the spreadsheet part.

10:23 It's just the fact that I can actually run Python scripts online off my computer in the cloud.

10:28 And I can just go there and it's there.

10:29 And so we said, all right, fine.

10:31 What if we dropped the spreadsheet bit and just had Python in the cloud?

10:34 What would that look like?

10:35 And that was Python.

10:36 Anyway, that's really interesting.

10:37 There's some parallels to Docker and .cloud, I think.

10:40 Totally.

10:40 In there, right?

10:41 Like, the thing that was just the foundation of your actual product became the product.

10:45 Yeah.

10:45 And the thing that worked so well.

10:46 Yeah.

10:47 The classic Silicon Valley pivot, although in this case, Silicon Roundabout pivot.

10:51 Yes, the Silicon Roundabout, which is, what, a few blocks away in London, that district.

10:55 Excellent.

10:56 Thanks for having me.

10:56 Thanks for having me.

10:56 Now, let me take a minute and tell you about our sponsor for the show, CodeShip.

11:09 CodeShip is a hosted continuous delivery service focused on speed, security, and customizability.

11:16 You can set up continuous integration in a matter of seconds and automatically deploy when your tests have passed.

11:22 CodeShip supports your GitHub and Bitbucket project.

11:25 You can get started with CodeShip's free plan today.

11:29 Should you decide to go with a premium plan, Talk Python listeners can save 20% off any plan for the next three months by using the code TALKPYTHON.

11:39 That's T-A-L-K-P-Y-T-H-O-N, all caps, no spaces.

11:44 Thanks to CodeShip for sponsoring the show, and I encourage you to check them out right now at CodeShip.com and thank them on Twitter where they're at CodeShip.

11:53 CodeShip.com and thank them for joining us.

12:24 Is it on multiple data centers or is it on one?

12:27 No, at the moment it's just in one.

12:28 And as we grow, we get a few customers going, hey, can we get some in Australia or can we get some on the West Coast or whatever.

12:34 But U.S. East one, A, B, C, D.

12:37 Somewhere in northern Virginia.

12:39 That's it, yeah.

12:40 I have cousins down there, a lovely countryside.

12:42 Fantastic.

12:43 Yeah, so I think that's a really interesting place to be in.

12:47 Like I said, the way I found about you guys is I'm actually hosting my website for the podcast on there.

12:53 Right.

12:54 And that thing is super responsive.

12:55 I really like the experience.

12:57 So I tried to find these other places that would host it, and they're like, oh, yeah, we'll support Python 2 and Python 3, but, oh, we don't support Pyramid, which is one of the framework I use for the website.

13:09 Or, yeah, we support Pyramid, but we only do Python 2, and I write it in Python 3, and I'm like, you know, because it's a brand new project.

13:15 Like, I can write this in, like, Python 3.

13:17 That'll be fun.

13:17 Until I wanted to host it.

13:19 Then it was not so much fun.

13:20 And I just stumbled across you guys, and I think what you're doing is really, really cool.

13:23 You know, you support a whole bunch of different interpreters, yeah?

13:28 Well, Python interpreters, yeah.

13:30 Of course, yeah, of course.

13:31 So you've got several versions of Python 2, several versions of Python 3.

13:35 Yeah.

13:35 PyPy, which I thought was just because you can, right?

13:39 Why not?

13:40 That is really cool.

13:42 Did you have to do anything special to support that?

13:44 No, no, it's okay.

13:45 So, I mean, supporting things from the web hosting point of view means we use UWSGI or MicroWISGI,

13:53 if some people have it in the background, and that just has plug-ins for various interpreters,

13:57 including non-Python ones.

13:58 So it's just a matter of activating the ones that we think we can do.

14:01 So, like, we could actually, if we wanted to, go off and make RubyAnywhere.com.

14:06 The trouble is, none of us know anything about Ruby.

14:08 So we could do it.

14:09 Technically, it wouldn't be hard.

14:11 But then I think we're taking on a lot of users that would be asking us questions that we don't know how to answer.

14:14 Right, sure.

14:15 And there's places that host Ruby, but you guys are hosting Python really well.

14:18 Yeah.

14:18 And that's the sweet spot.

14:19 I mean, there's lots of people out there in there.

14:21 You know, so if you're someone going, oh, okay, I want to run my code on some servers,

14:25 like whether that's for web hosting or anything else.

14:28 But, you know, you can go to Amazon straight.

14:30 You can run your own server in a cupboard.

14:32 You can go to Google App Engine or Compute, as it's now called.

14:38 Or you can go to Heroku or you could go to .cloud in the old days.

14:42 And so it's about sort of figuring out where there's a space in that sort of fairly crowded market.

14:48 And I think the one is, like, let's focus on Python because that's what we know.

14:50 And there's plenty of business there.

14:52 And then let's try and say, okay, well, the hard work if you're running your own server is all the kind of sysadmin and configuration and maintenance.

15:00 There's this kind of tradeoff between, like, the ultimate flexibility is if you do everything yourself.

15:04 Right.

15:04 Go to Z2, start up in Linux machine.

15:07 Yeah, yeah, yeah.

15:08 But then it's your Linux machine you've got to babysit.

15:10 Yeah.

15:10 So it's more effort.

15:11 So, like, more flexibility, more effort.

15:13 And then there's, like, the other end back in the old days, like Google App Engine, where they would do a lot of the work for you, but they were also very restrictive.

15:19 So we'd say, right, well, you can use App Engine, but, you know, these are the rules about what kind of things you can run.

15:23 It's this version of Python.

15:24 You know, these things won't work.

15:26 And you have to, you know, like, all your requests will be killed after X seconds.

15:29 Don't touch the files.

15:30 Yeah, no database, no nothing.

15:32 And so we, like, so we're sort of somewhere between those two, trying to give, like, there's enough flexibility that people find it interesting.

15:38 Whilst solving enough of the problems that developers don't want to have to think about.

15:42 You know, scaling, backups, load balancing.

15:45 Yeah, so maybe we could talk about the sort of experience of creating a website in there.

15:49 And then we should also talk about other things like web job type stuff, which I think is interesting.

15:55 But you go there, you say, I want to create a website.

15:56 You can do that for free, right?

15:58 Right.

15:58 So I can create a free website as long as I don't care about the domain name.

16:01 Yep.

16:01 It would be .pythonanywhere.com.

16:03 Yeah, exactly.

16:04 Something .pythonanywhere.com.

16:05 Your username .pythonanywhere.com.

16:08 That's right.

16:09 And then I'm giving something that's really interesting.

16:12 It says, here is your bash shell in a browser.

16:16 Yeah.

16:16 To configure your environment.

16:18 Yeah.

16:18 Yeah.

16:19 And basically I can start with, like, a virtual environment.

16:23 Yeah.

16:23 Yeah.

16:24 Exactly.

16:24 I mean, so we haven't done enough about this, but we want to try and so, you know, people who learn Python, there's a sort of first learning curve, like, trying to get it installed and figuring out how pip works and can you install packages.

16:38 And we try and solve that problem for people by just saying, look, Python is already installed.

16:43 Here it is.

16:43 You just type Python or you click this button that says which version of Python you want.

16:47 And then, you know, like, how do you install packages?

16:49 Well, here's pip.

16:50 It will just work.

16:51 And also we've pre-installed a bunch of them just of popular things.

16:54 So maybe it's already there.

16:55 Nice.

16:55 Like, what are the popular ones you have installed?

16:57 We have, like, a file that we have overdone it.

16:59 There's, like, a thousand packages installed.

17:01 Like, SciPy, NumPy, Pill, blah, blah, blah, blah, requests.

17:05 And so many of them.

17:07 Yeah.

17:08 But in the web apps thing, it's the same thing.

17:11 And they go, okay, well, great.

17:12 I've developed a little, you know, I want to develop a web application.

17:15 What do I do?

17:15 Well, you know, now you're going to need to install this web framework.

17:18 You need to configure the following settings files.

17:21 You need to have a folder structure that looks like this.

17:22 You need to put your static files over there.

17:24 And if you're on a web server, then you'll want to configure, you know, a static file serving here and a database there and an environment variable there.

17:30 And we just want to try and do as much as possible to try and just kind of give users a thing that works.

17:36 They can get started with it.

17:37 And so we've tried to do a bit of that.

17:39 And so we've tried to do a bit of that.

17:41 So if you want to start, like, a Django project, you can go to our web tab, go start a new project.

17:47 Do you want to use Django?

17:47 Yes.

17:48 And we'll install Django for you and set up a basic sort of run the sort of Python manage.py start project for you.

17:54 And there'll be a working Django site there.

17:57 And you can start with that.

17:58 Yeah.

17:58 That's the idea.

17:59 And, like, you know, we need to do more work.

18:00 The version of Django we have for Python 2 if I'm nitpicking is out of date.

18:03 So then, okay, you do have to use a virtual environment.

18:05 And that's a bit more complicated and blah, blah, blah.

18:07 I think the fact you have the virtual environment possibility there means that you can do whatever you want more or less on the system.

18:15 But you don't have to manage the infrastructure.

18:18 And so in my mind, I think you guys are a very interesting blend of platform as a service and infrastructure as a service.

18:24 So, like, I see it as infrastructure because I get a bash shell.

18:28 I can really kind of install stuff.

18:30 I can work with the file system.

18:31 It's kind of like a VM.

18:32 But it's platform as a service because I don't care what the web server version is.

18:36 I don't care about Linux and I'm setting that up.

18:39 Yeah.

18:40 You take care of it for us, right?

18:42 Yeah.

18:43 I guess.

18:43 So that's right.

18:44 Some other people will try and hide some of that stuff from you and just give you a thing where you write some config files and then...

18:50 Like Google Compute, for example, right?

18:53 Yeah.

18:53 And then, like, magic happens.

18:55 And ours is a little bit...

18:56 Maybe it's more about trying to recreate the kind of environment you have on your own laptop when you're running a dev version of a Flask app or something.

19:04 You know how that works.

19:06 Making that as much as possible the same on Python Anywhere where you just go, okay, well, if I wanted to edit a file in Bash or whatever, I can.

19:13 And it's just that this part over here will do the web serving of it.

19:17 Or if I want to view my log files, I can just, you know, tail my log file over here and there it is.

19:22 So I don't have to go through some complicated UI to go and retrieve the log file, you know, it can do it in Bash.

19:27 Yeah, that's really cool.

19:28 I feel like, you know, it's a nice middle ground because...

19:32 I'm getting more enthused about my own website by talking to you about it.

19:35 It's all you should.

19:35 This is great.

19:35 This is fantastic.

19:36 I'm here to make you excited.

19:38 Keep you going because you're doing awesome stuff.

19:40 So...

19:41 Thank you.

19:41 I feel like you're making me maintain things but making me maintain the right things.

19:47 So I've created a virtual environment and everything in the virtual environment is my problem.

19:50 But that's cool because I decide when I upgrade Pyramid or Requests or whatever, and that's all in line with what my app's doing.

19:57 But everything else I don't care about, right?

19:59 Like, would you upgrade Python 3 for me at some point?

20:02 Like, would I just magically switch to a new version of Python?

20:05 Well, you need to rebuild virtualenv if you switch to Python.

20:08 Right, of course.

20:09 That's right.

20:09 But we're trying to be a bit clever about that.

20:11 And we're trying to think of ways where you can say, you know, virtualenv is actually a bit scary for beginners.

20:15 Sure.

20:16 Like, they're used to going, all right, I figured out this command line thing.

20:19 I know that if I type Python, I'm going to get a Python prompt.

20:22 Okay, fine.

20:23 And then you go, right, but, aha, you need a virtualenv.

20:26 And so that when you do your command prompt, you have to check, have you activated the virtualenv, and is it the right one?

20:30 And, like, this is another point at which some big N is just going to go, what?

20:33 I just forget it.

20:34 Yeah, it's scary.

20:35 So people get that wrong.

20:37 And so that's why we try and give a default no virtualenv setup that might work.

20:41 And then we try to see if there's ways we can maybe build a bit of a GUI around the virtualenv stuff one day,

20:47 where you say, like, a virtualenv is a thing that Python Anywhere understands.

20:50 And so it knows what your virtualenvs are.

20:51 And we can give you a GUI that says, this is what your virtualenvs are.

20:54 And if you don't want to edit your virtualenv through bash with, you know, pip freeze angle bracket requirements.txt,

21:02 maybe we can give you a UI for that, and then you can selectively click on things and upgrade them.

21:06 Yeah, you could surface, like, the top 100 most popular packages, and they could check them off.

21:11 Yeah, yeah, yeah, yeah, exactly.

21:12 So things like that.

21:14 But that's, I mean, that's Vaporware, so I apologize for talking about it.

21:17 No, but these are good ideas.

21:19 I think it would really move it down farther.

21:21 So web hosting, you said, is kind of what people who are paying you, people like me, are doing.

21:27 But there's other stuff you can do as well, right?

21:29 Like, one thing I saw is I can run, like, scheduled jobs.

21:31 So if I want to, you know, like, run a script that, like, sucks down some sort of screen scraping type thing.

21:37 Absolutely.

21:38 Beautiful soup.

21:38 Yeah.

21:39 I can do that, yeah?

21:39 A lot of people do that, yeah.

21:40 So a lot of people are using it for web hosting.

21:43 A lot of people do scraping.

21:44 And so we have this thing, scheduled tasks.

21:46 It's basically cron jobs.

21:47 Yeah.

21:47 And you get to say, oh, yeah, every hour, every day, this sort of time, I'd like to run this script, whatever script you want.

21:53 And we'll go ahead and run that for you.

21:54 And maybe it's, you know, pulling down some data and saving it to a database, which maybe you've also got a web app that's then displaying that data.

22:00 I don't know, show me the train times or something.

22:02 Whatever.

22:03 Yeah, so people do it to, like, run automated jobs that they don't need to keep their own computer switched on for.

22:09 And then the third category of user, I guess, who might pay us are people doing big number crunching.

22:16 So every so often we get some people coming along going, right, I want to just download megabytes and megabytes of tweets and, like, just run massive number crunching sentiment analysis on them.

22:27 And so we have a system where if you use a certain amount of, like, CPU power on the system, we kind of put a quota on that each day.

22:36 When you go past that quota, we don't switch your stuff off.

22:39 We just put it in a tar pit where it gets slowed down.

22:41 And so if you want to do a lot of number crunching all day long, then you have to pay us to get a higher quota so that it's actually going to run at a reasonable speed.

22:49 Right.

22:49 That's the deal there.

22:50 Your web apps don't have that restriction right now, do they?

22:53 So they don't count towards your quota?

22:56 Yeah, yeah.

22:56 We find most web apps aren't big number crunching sources.

22:59 And we do actually have a thing where if a web request hasn't responded within, I think, the limit is five minutes, we kill it.

23:06 That seems reasonable.

23:08 It seems reasonable to us.

23:11 So, yeah, you could try and very cleverly circumvent our number crunching restrictions by building a web app if you want, but it would be pretty painful.

23:19 Yeah, no, I'm just more like thinking it's just not something you have to worry about with web hosting.

23:23 It's more of a jobs sort of consideration, right?

23:26 That's right.

23:26 Yeah, yeah, yeah.

23:27 Because I was feeling really good.

23:28 I'm like, after a half a day, I have a lot of hits on my site.

23:31 So I've used up 0.00 seconds of my time.

23:34 I'm like, wow, I wrote that thing pretty efficiently.

23:36 But not really, right?

23:37 No, that's right.

23:38 We don't count the web hits.

23:39 And the web model in general is that, you know, like, so it's like any, what do you call it, shared multi-tenancy?

23:47 I don't know.

23:48 Yeah.

23:48 But the point is that you can, like an airline booking system.

23:52 Oh, God, I just compared myself to an, I compared our website to an airline booking system.

23:56 This is the worst PR ever.

23:57 You know, like, we can host a lot of people on a big web server, and most of them are, like, not going to be doing very much.

24:04 And every so often, if someone hits the front page of Hacker News, you know, if you run your website on an Amazon micro instance, right, it's pretty fast most of the time.

24:14 And the way Amazon work is that, you know, they'll do really, really fast hits on requests.

24:19 And once you've used about 10 seconds of continuous CPU power, they throttle you down to nothing.

24:23 Yeah.

24:24 Right.

24:24 So it's great for running a website that gets low traffic, and it's super cheap, and it can be free.

24:29 But then if you hit Hacker News, your website just goes down.

24:33 Yeah.

24:33 Whereas, long on all.

24:34 When you need it most, it lets you down.

24:35 Like, the one you finally have gotten the word out about, and it's toast.

24:40 Right.

24:40 So whereas we say, hey, look, like, we're running, so you're on servers that have spare capacity.

24:45 They're big servers.

24:46 We use triple extra larges.

24:48 I forget which one on Amazon.

24:50 So when someone gets, you know, Hacker News, they just start using up more of the CPU on that instance for however long they're at the front page of Hacker News for.

24:58 And that's, like, we're fine with that.

24:59 That's part of the plan.

25:00 You know, if it turns out you're still at the front page of Hacker News after several days, like, we are going to notice, and we're going to have a quiet word with you about maybe it's time to start paying us.

25:09 Yes.

25:10 But in the meantime, it's a nice thing, so you don't have to be scared of that sort of getting slash dotted moment.

25:15 Yeah.

25:15 A friend of mine said, when I told him I was using your service, Python, and he said, well, why don't you just go to EC2 and create, like, a micro Linux?

25:25 I'm like, one of the things I really liked is it's really running on a big machine, and it has a lot of power.

25:31 It's just kind of shared, but, you know, those spikes kind of even out.

25:35 And so it seems like it's way more responsive than a micro instance for me.

25:40 Yeah.

25:40 Yeah.

25:40 So that's the idea.

25:42 It's like we can provide that.

25:43 Within reason, we can scale up for when you get crazy traffic unexpectedly.

25:49 And if it turns out to be forever, then we're just going to come after your money.

25:52 It seems fair.

25:54 Gently encourage you to upgrade.

25:55 It seems fair.

25:57 So other than, of course, talkpythontome.com, are there other notable moments that you guys can talk about?

26:05 Certainly, talkpythontome.com is our favorite website.

26:08 I would say so, yeah.

26:10 If it's not the one that's getting the most hits, it is certainly the best one.

26:12 Well, yeah.

26:16 So who do we host?

26:18 We've got a sort of funny niche in the Web2Py community.

26:21 So we host Web2Py.com, and we've got lots of users of that site.

26:25 And then a sort of case study example we sometimes trot out, which is a terrible example.

26:34 Again, bad PR, but it's just fun.

26:35 There's this guy.

26:38 He's a student at university, and he made a website called Stereodose.com.

26:43 Stereodose.com.

26:45 Is that D-O-S-E?

26:46 Yeah.

26:46 Yeah, and the Stereodose.com website is very simple.

26:49 What it says is like you come into a screen.

26:52 It says, pick your mood.

26:53 And it sort of says like energetic, mellow, a couple of other choices like funky.

26:59 And then screen number two says, pick your drug.

27:02 Right?

27:03 And you get to choose acid, mushrooms, ecstasy, weed.

27:06 And then it's going to auto-generate a playlist for you that's appropriate to your mood and drug of choice.

27:11 Fantastic.

27:12 Right?

27:12 So he's a university.

27:13 He's a college, right?

27:14 This is hugely popular.

27:16 I've asked all his friends.

27:16 So he knocked this together in no time.

27:18 It's a simple website, right?

27:19 And he hosted it with us.

27:21 And so he had the equivalent of hack and use.

27:24 I don't know what the equivalent of hack and use is for drug-induced playlists.

27:27 But he got on that.

27:28 And so he went from 10 hits a day to 10,000, 100,000 an hour.

27:35 And we were just like, yep, fine.

27:36 Very mellow hits.

27:38 Yeah, some of them.

27:39 Some of them were like really hyperactive.

27:41 Just keep refreshing the thing.

27:44 That's pretty cool.

27:46 Yeah, so that's an example.

27:48 So he made that thing.

27:49 Out of nowhere, it got popular.

27:50 And then we were just able to handle that fine.

27:52 And then gently suggested that now he's making some money off advertising.

27:55 Could he pay us X dollars a month?

27:56 I think, yeah.

27:58 Probably he's still on quite one of the quite low plans, like $20 a month.

28:01 Yeah, yeah, probably.

28:02 And so that's very cool.

28:04 Well, we do that for some of the first customers that have a big hit.

28:07 We like to reward them by keeping them around at a price that's quite frankly cutting our own throats, Michael.

28:12 Cutting our own throats.

28:13 What can you do?

28:14 It's what you have to do now.

28:15 It's what you have to do.

28:16 So we were talking earlier before we started recording.

28:20 You said you do a lot of Python sort of end-to-end of the whole thing.

28:24 So looking in from the outside, obviously, it's interesting that I can host Python there.

28:29 But can you talk a little bit about what the internal usage is and how that goes?

28:34 Yeah, yeah.

28:34 So it's all Python inside as well.

28:35 It was the same.

28:36 So the guys talk about Resolver Systems and that spreadsheet product.

28:39 They decided to start building it in Python and they were going to target Windows.

28:43 So they built it in Iron Python.

28:44 Okay.

28:44 And they went, hey, let's build it in Iron Python.

28:46 And then, like, obviously, it'll get too slow at some point.

28:48 And then we'll start writing some C or some C#.

28:51 And they found with that they just never reached that point.

28:53 Like, they just keep going in Python.

28:55 It was fine.

28:55 And so we had a similar approach with Python anyway.

28:57 And they said, well, Python is what we love.

28:59 It's the fastest way to get websites built that we're going to be able to do.

29:03 So let's just start with that and see if we ever need anything else.

29:05 And no, we don't really.

29:07 I mean, there's about four lines of lua somewhere.

29:11 And there's a bunch of JavaScript, obviously, which is a nightmarish help.

29:17 Yeah.

29:18 But other than that, yeah, no, it's all Python.

29:20 I'm just trying to think of any exceptions to that.

29:23 Python 2?

29:24 Python 3?

29:25 Well, yeah, Python 2.

29:27 Yeah, of course.

29:28 Well, we're joining a club with literally everybody else.

29:30 But I think you are doing a good deed to have a wide variety of interpreters, right?

29:36 Like, even PyPy is super cool.

29:38 Yeah.

29:38 Yeah.

29:39 Yeah.

29:39 I mean, yeah, so making the choice to sort of start supporting Python 3 for web apps, for example.

29:44 You know, just having Python 3 around, I mean, you can install it on your own computer in seconds.

29:48 So that's fine.

29:48 It's like supporting it for a real thing on the internet, like an application was, you know, we were looking at it going, is this going to be a niche concern?

29:56 But then we were saying, look, a lot of the people who come to us are beginners or hobbyists or not professional programmers.

30:01 And the message out there is, yeah, you should use Python 3.

30:04 And so to support them well, I think we did.

30:06 We did have to go, okay, well, even if we're not using ourselves right now, the wider world, yeah, our users want this.

30:12 So, yeah.

30:13 For sure.

30:14 That's cool.

30:14 Yeah.

30:14 I talked with Kenneth Wright.

30:17 Yeah, I had that.

30:17 About Python 2 and Python 3.

30:20 And, you know, it seems like it's some of the little things that make a big difference.

30:25 He said that having Django switch their docs by default to Python 3 made, you know, a noticeable bump in the usage for web apps for Python 3 just doing that.

30:35 So things like, you know, having it available.

30:36 Yeah.

30:37 Lowering the friction.

30:38 Yeah.

30:39 I think that's happening.

30:41 I heard the Kenneth episode, actually.

30:43 And he was saying, I wish Python.org would just decide which one the version is that they want to push and have that as the one that appears when you download.

30:50 And that should be Python 3.

30:52 And if you want Python 2, you should go and have to search for it.

30:55 Because ultimately, I think, yeah, beginners are using Python 3.

30:58 Educators are using Python 3.

31:00 Hobbyists are using Python 3.

31:01 Because, you know, why would you use the old version?

31:03 Like, if you don't know any different.

31:05 And so, Python 2 is kind of a legacy language.

31:08 It just so happens that this is the one that 90% of professional Python developers use.

31:12 But, yeah, I think we should make every effort, I guess, to start supporting Python 3 first for that sort of community.

31:18 Yeah.

31:18 He was talking about some really interesting ideas of, like, what is the killer feature we need to actually make people go, okay, it's time to switch.

31:25 Like, removing the global interpreter lock.

31:27 Maybe making, like, a super simple way to build distributable binaries that have no dependencies.

31:33 I think those would be really cool things to work on.

31:35 And I think it would make a difference.

31:37 You brought up education.

31:39 Yeah.

31:40 And you guys are probably used a lot for students and people trying it out.

31:44 Or there are, like, classes or university classes.

31:47 Like, okay, go create your Python in your account to start your project.

31:49 Yeah.

31:50 Yeah, there are, actually.

31:51 So, one of the things with Python is that it's the most popular education language for good reason, I think.

31:56 It's just really straightforward.

31:58 Like, you know, if you...

32:00 I'm not Guido Van Rossum, but if you were to try and design the most obvious way of writing a programming language, that's how it is.

32:07 Like, if you think about how a for loop works in Python versus C++ or JavaScript, you know, you just go, I just want to loop through these items.

32:15 So, for each item in the thing, I want to do a thing.

32:17 And you look at Python, that's actually it, isn't it?

32:20 That's fantastic.

32:21 So, for beginners, that's great.

32:22 Like, the learning curve is really nice for Python.

32:24 It's, you know, the Zen of Python is there.

32:26 Within the language, that's great.

32:29 So, that's working.

32:30 Outside the language, there's some peripherals where it's not so good.

32:33 I saw someone doing a poster about this at a PyCon three years ago.

32:38 Just saying, you know, here's what beginners find hard about Python.

32:41 Installing it is hard.

32:43 Like, first, you have to choose between two and three.

32:45 And then you install it on your system.

32:47 And, like, I don't know if you've done this on Windows recently.

32:49 I have.

32:49 It's beautiful.

32:50 Like, it doesn't add itself to the path.

32:52 And it still doesn't add itself to the path by default, by the way.

32:55 And so, then when people go, oh, just open up a command.

32:58 Try to type Python.

32:59 Like, it doesn't happen.

33:01 Python not found.

33:02 And, you know, it's like getting Python installed.

33:05 And then people say, oh, yeah, you need pip to install packages.

33:07 You know, so just, you know, apt-get install pip or brew install pip.

33:11 And beginners go, what?

33:12 What does this apt-get?

33:13 You know, we've got Windows.

33:14 Everyone's got Windows.

33:15 We have no apt-get.

33:16 And even the ones that have Macs, right, they go, oh, yeah, just install Homebrew.

33:19 And they go, what's Homebrew?

33:20 And they find a GitHub page, which is a terrifying thing, right, for beginners.

33:24 And the GitHub page just says, oh, yeah, you just need to download Xcode, which is 1.1 gigabytes,

33:28 just to be able to install this thing that's going to help you install this thing, right,

33:33 that maybe you think you need.

33:34 What is it, like, five Macs or something?

33:36 I mean, how big is pip?

33:37 I haven't even looked.

33:38 It's totally small.

33:39 pip is tiny.

33:39 But, like, to install it on a Mac, people tend to say, oh, yeah, use Homebrew.

33:42 And then, so I have to, like I say, you have to hop by this 1.1 gigabyte thing,

33:47 which is going to help you install this thing, which is going to help you install this thing,

33:49 which finally is what you need to install this thing that you hope to use for some programming.

33:53 And, yeah, people have given up by now.

33:55 Yeah.

33:56 I think people sometimes forget what is obvious to us now, but the things you get hung up on,

34:03 like you're saying, like the path, you know.

34:05 It would be no big deal to us.

34:07 We could easily go do it.

34:08 It's not fun.

34:09 But to new people, they're literally out of luck, right?

34:12 Yeah.

34:12 It's like, what do I do?

34:13 Yeah.

34:13 Yeah.

34:14 Yeah.

34:15 And so you guys make that easier, right?

34:17 Well, yeah.

34:17 So teachers, you know, have to, if you're teaching Python, you have to, like, face that learning curve.

34:22 And if you've got a bunch of students in a school, then you go, right, let's get Python on all the computers.

34:28 Go.

34:28 And then the school IT department goes, well, we're an IT department, so we say no to everything.

34:32 It's our job.

34:34 You know, or I don't mean, you know, there's great school IT departments out there, of course.

34:38 But, you know, maybe that's going to take time or maybe, you know, whatever.

34:42 Or you are, you know, teaching Python to a bunch of people out there, maybe adults, or they've got a disparate bunch of laptops.

34:49 Some of them have got Windows.

34:49 Some of them have got, you know, like, Macs.

34:51 And you've got to try and make sure each one of them has got Python installed.

34:54 And you've got to try and make sure each one of them has got a text data to install.

34:56 And then you've got to be like, hey, if you're using sublime text, it looks like this.

35:00 Or if you're using idle, it looks like that.

35:02 Or if you're using a Mac, then type this command.

35:04 If you're using a PC, type that command.

35:06 And so, you know, a lot of people teaching Python is the first day has just been installing Python.

35:11 And they go, well.

35:12 Programming's not fun.

35:13 Programming sucks.

35:14 It's all about these little settings, right?

35:16 Right.

35:16 And so then if you just say to them, okay, well, forget all that.

35:18 Like, if you go to Python anywhere, you need a username, you choose a password, and then go.

35:22 Everyone has a text editor that works.

35:24 Everyone has the same bash prompt.

35:26 Everyone has the same version of Python.

35:28 And everyone has the same packages all available and pre-installed.

35:31 So if you want to do a class on NumPy, you can hit import NumPy.

35:34 You don't even need to explain pip install.

35:36 Yeah.

35:36 You haven't even mentioned that on Windows, you might not have, like, the clang compiler or GCC or VSVars.bat.

35:46 Yeah.

35:46 VSVars.bat.

35:47 That will literally stop the beginner in their tracks.

35:51 If, like, the path thing didn't get them, that will definitely get them.

35:54 Yeah.

35:54 So that's great.

35:55 So it's all set up.

35:56 Even the stuff that's harder to install, like NumPy, are the things that have C dependencies.

35:59 Yeah.

36:00 So teachers, like, have been, you know, coming to us for that.

36:04 And we've recently decided to try and do a little bit more for education.

36:08 As education in Python worldwide becomes more and more popular.

36:13 In the UK over here, the government have decided to make it part of the national curriculum.

36:17 So they're saying that you have to teach it in schools.

36:19 And this isn't just, like, you know, sort of secondary schools.

36:22 It's, like, it's middle schools.

36:23 So, you know, seven, eight, nine-year-olds are going to start to learn programming.

36:28 And, you know, what can we do to try and, like, help teachers who, like, some of these teachers, they're not computing teachers, right?

36:36 These are, like, generalist teachers who are just going, well.

36:38 They might be a science teacher or something.

36:39 I don't even like computers that much myself.

36:41 I don't know if I, you know.

36:42 So they're just trying to stay one week ahead of their students.

36:44 And so if we can do something to try and make their lives a bit easier.

36:47 So, yeah, we've been doing a bit of that recently, and it's been really cool.

36:50 Yeah, it's really great.

36:51 Last episode, I talked to a guy named James Curran.

36:55 And in Australia, he's involved in the curriculum there for high school and said that in Australia, they're requiring a text-based programming language as part of the high school curriculum.

37:08 Yeah.

37:08 And so that really natural.

37:09 Yeah, and he can't require two because we're sort of twice as good as Australians.

37:12 Nice, yeah.

37:14 So I think Python is the natural choice if they say text.

37:17 You know, you can do Scratch or something like that for beginners.

37:20 But as soon as it's, like, you've got to do a, quote, real programming language, I think Python is a good choice.

37:25 Yeah, in the UK, it's equivocated.

37:26 So people tend to teach HTML and Python, which, you know, you can have an argument about that.

37:32 Yeah, my daughter's in their high school have a class called Web Coding, and they learn HTML.

37:36 Yeah.

37:37 I'm not sure HTML and coding go together, but whatever.

37:39 They're doing something with computers, and it's cool.

37:41 Well, CSS is true and complete.

37:43 Accidentally.

37:44 Accidentally.

37:45 Nice.

37:47 Okay, so talked about people getting started.

37:51 That's great.

37:51 Talked about the web hosting.

37:53 Another thing that you're really into, and you were recently at PyCon last year, right?

37:58 Mm-hmm.

37:59 Or was it this year doing a workshop or tutorial?

38:01 All the PyCons.

38:02 All of them.

38:03 Yeah, yeah.

38:03 All of them.

38:04 On testing, right?

38:05 Sure.

38:05 Testing a Django app.

38:06 Yeah, yeah.

38:07 Yeah, so that's my shtick.

38:08 So I guess it was in 2009, 2010 that I started with Resolver and what became Python Anywhere.

38:16 And I guess I'd learned enough Python and Django to be dangerous.

38:22 And I'd built my first kind of web application for a client.

38:27 And I remember how this went.

38:29 Have you read Dive Into Python?

38:33 I think I've skimmed it.

38:36 I haven't read it all the way.

38:37 To Dive Into Python is a good intro to Python for someone who already knows another programming language.

38:44 And in about chapter 10, he starts talking about testing and test-driven development.

38:49 And he goes, you know, we've learned about how Python works by RR.

38:52 Now let me tell you a bit about testing and how you can write tests and how you can even write them first.

38:57 And he uses a very traditional example, which is a Roman numeral translator.

39:01 So let's build a function that can translate Roman numerals into integers.

39:05 So like I is going to become 1 and II is going to become 2 and IV is going to become 4 and so on.

39:09 And he goes, so, you know, imagine how you do that.

39:12 And let me show you that if you actually, you can write tests for this.

39:15 You can write a thing that says I should equal 1 and II should equal 2.

39:19 And you can run that as a program which tests, you know, the thing you're about to write.

39:23 And then when you write it, you know when you've got the right answer.

39:26 And secondly, you know, you're going to be able to modify your solution and know that it's still correct.

39:30 And I remember reading that and going, you know what, that's a really good idea.

39:33 That sounds like something you really should do.

39:37 It's like it's healthy.

39:38 It's good for you.

39:38 It's like flossing your teeth.

39:41 And what happened next is I got my first real client and there were real deadlines.

39:46 And all of my good intentions about TBD just went right out the window.

39:49 And besides, by then I'd had a full seven or eight days of experience with Python and Django.

39:54 You had it all figured out.

39:56 I thought I was pretty smart.

39:57 I figured I could get away without tests.

39:59 And yeah.

40:00 Yeah.

40:01 Actually, I was fine.

40:02 I was absolutely fine.

40:04 Yeah.

40:05 At first.

40:06 And then.

40:07 And then you started maintaining that thing.

40:09 Yeah.

40:10 Yeah.

40:10 Yeah.

40:10 Yeah.

40:10 Yeah.

40:11 I mean, you know, I read a thing about like called Don't Repeat Yourself.

40:14 And I was like, right, well, I better not repeat code.

40:16 And so like I started to that ended up being like sort of an inheritance class hierarchy, five levels deep.

40:22 Did you hear that siren?

40:26 Well, it's 4 p.m. on a Tuesday.

40:29 So I guess that means it's a perfect time for a fire alarm test.

40:33 It was ridiculously loud.

40:35 Now, let's pick up the conversation again after ears stopped ringing.

40:38 So you had written this app and it started out all fine.

40:42 Then you heard about the derived principle.

40:45 And you're like, yeah, that's a good idea.

40:46 Let's do that.

40:46 Yeah, yeah.

40:46 Let's do that.

40:47 Let's have an inheritance hierarchy, five levels deep.

40:49 And like for some reason, I decided that like somehow I'd got to eval statements, right?

40:54 So there was eval statements in the code doing stuff.

40:56 And, you know, like it was no longer a one page app.

40:59 You can just check works by like checking that one page.

41:01 Like there was 25 pages and they were all interdependent.

41:04 And I would change the thing over here and go, oh, I think I could.

41:07 Oh, no, that's going to break that one over there, I think.

41:09 So, but what?

41:09 Maybe if I override this method.

41:11 And like pretty soon I had like a nightmare of crufty code and I was scared to change it.

41:16 And, you know, like all of those things happened to me.

41:18 So, yeah.

41:18 So then I got a job at Resolver and they went, you know, we do test driven development.

41:23 I'm like, oh, really?

41:24 Okay.

41:24 Maybe that could help.

41:25 But I still dragged my feet about it.

41:27 But, you know, yeah, they showed me this thing.

41:29 And so it's an extreme programming shop.

41:32 Everything is pair programming.

41:33 Really?

41:33 That's cool.

41:34 Yeah, yeah, yeah.

41:35 I mean, it was like honestly so lucky for me to learn from these guys who've been doing it for ages.

41:41 And, you know, if you're a pair programming and you just sit next to someone and they start asking programming and you just sit there going, why?

41:46 Why?

41:47 You know, and it's just like a sponge just sucking in all this knowledge.

41:52 So it's an amazing way to learn.

41:56 It's almost like an apprenticeship type of thing.

41:59 Right.

41:59 Yeah, I mean, that's really true.

42:00 Yeah.

42:01 And so that's, yeah.

42:02 So I learned all this testing and I decided to try and kind of like regurgitate it a little bit and turn it onto some online resources.

42:11 I made a couple of blog posts.

42:13 I rewrote the Django tutorial.

42:14 You have a website, right?

42:15 Yeah.

42:15 Yeah.

42:16 It's called obeythetestinggoat.com.

42:19 Fantastic.

42:20 I used to have a website called tddjangotutorial.com.

42:23 And what it was was like the official Django tutorial except test driven.

42:26 So it tests at every stage.

42:27 That's nice.

42:28 And that turned into like a sort of tutorial I would do in real life and at conferences.

42:32 And that eventually turned into a book which is published with O'Reilly.

42:36 It's called obeythetestinggoat.com.

42:38 Unfortunately not.

42:39 No, I had, yeah, we discussed this with my editor and obeythetestinggoat is going to be too arcane a title.

42:45 So that is actually the tagline or the subtitle.

42:48 So the book itself is called test driven development with Python colon or comma obeythetestinggoat colon.

42:56 And we actually argued about this.

42:58 I wanted an exclamation mark but they insisted on a colon.

43:01 So it's obeythetestinggoat colon tdd with Python, JavaScript, Django and pals or something like that.

43:06 That's fantastic.

43:07 So what kind of stuff do you cover in there?

43:09 So yeah, it's test driven development but instead of taking that sort of classic slightly artificial example of a Roman numeral calculator which everyone does or a banking currency converter, right?

43:21 There's always these TDD tutorials with like an example function and it goes, oh yeah, but it's nothing like the code you write in real life.

43:27 It has no dependency.

43:28 Right.

43:29 It doesn't touch the file system.

43:30 It doesn't have like a huge bunch of code calls, all that kind of stuff, right?

43:34 And so I just did the opposite of that.

43:36 I went like, okay, well let's do actual web development.

43:39 And we'll just have all the dependencies.

43:40 So yeah, it will be a web application which needs a web browser and it needs the file system straight away because of templates and there's going to be a database and all that is like from the ground up.

43:49 But maybe that's a hideous mistake.

43:51 I don't think so.

43:52 I think a lot of those, I do a lot of training for my job and a lot of people have the same reaction that you were saying is like, it's all well and good to tell me about this stuff but this is a fake thing.

44:05 It won't work in my complex company because X, Y, and Z.

44:08 And if you don't see it for real, then who's going to believe it, right?

44:12 So yeah.

44:13 I mean, it's still a fake thing.

44:14 I mean, I go through the development of a web application from scratch, but it's a simple web app, right?

44:20 It's a to-do list app because that's everyone's example and I have no imagination.

44:25 So it's the simplest possible web app, but it does have a database and it does use a web browser and it does do things to the file system and whatnot.

44:33 Nice.

44:34 So what are the testing frameworks and things?

44:39 Like do you use pytest, Unitest, Nose, Clean Green?

44:44 What's the story on it?

44:45 It's been Clean Green.

44:48 Nathan.

44:49 I met Nathan who did this green testing framework.

44:52 He's a lovely guy.

44:53 His GitHub username is CleanCut and that's because he's just got the most preppy set of teeth.

44:59 I think he's saturizing himself a bit.

45:04 Nice.

45:04 Yeah.

45:05 No.

45:05 So for the book, I just use the kind of standard air quotes tools, which are the UnitTest, Standard Library, Test Framework, and the Django Test Runner because that's what most people use.

45:19 And at work, we use those as well.

45:23 And we've also started experimenting a little bit with pytest.

45:26 So there's a few talks out there if you look at it.

45:29 I'm saying pytest versus Nose versus UnitTest.

45:32 What are the pros and cons?

45:34 And the Noses and pytest do come off well when they say, you know, like, UnitTest came from the Java world and this sort of like XUnit thing, which involves classes and it involves methods.

45:44 And, you know, they've got these camel case method names, which is they've got them for historical reasons.

45:49 And people new to Python will look at that and go, oh, that's weird.

45:52 Why are we using camel case here?

45:53 They don't look like methods on anything else I've ever seen.

45:56 And so moving away from that, the pytests and the Noses who have a more just why have a class?

46:01 There's no point.

46:02 Let's just have functions because that's all we're really using these classes for.

46:05 And that has a lot of appeal.

46:07 And so I've dabbled with that and we've dabbled with that at work.

46:10 And I think they're kind of cool.

46:11 So I would definitely recommend people take a look at those.

46:14 And particularly, I think pytest has got a lot of – I get the feeling that, you know, people have been out there and looked at these things.

46:19 pytest is coming out as like the new kid on the block or the one where people go, yeah, yeah, yeah.

46:24 Having assessed all three, this is the one to look at.

46:26 What do you think the benefits are there?

46:28 Is it more Pythonic?

46:30 Yeah.

46:30 Is it easier to use?

46:31 Yeah.

46:33 So those two things, for example.

46:35 Yeah.

46:36 You know, like so in unit test, you're going to have – you know, you go, well, if I write a test without any framework, I go assert thing equals three.

46:45 Right.

46:46 This is actually – I do this in the book to explain why would you use a test framework.

46:49 And you go assert thing equals three and it fails.

46:52 And you get a thing saying assertion error.

46:53 But it doesn't say, well, thing you expected was three was actually equal to four.

46:57 That would be useful.

46:58 That would be great.

46:58 So you can write your own error message handler, right, by, you know, using the sort of comma second argument to the assert keyword.

47:05 But that's hard work.

47:06 And you know what?

47:07 People have discovered these problems before and there are standard solutions.

47:09 And one of them is use unit test, put in a test method.

47:12 You get set up and tear down, which is a common requirement in tests.

47:15 And you can go self.assert equal thing with thing and then it's going to give you a nice error message.

47:20 And I think that's all very well.

47:22 But you've gone through the trouble of making a class and making a test method.

47:26 And you're – I think Raymond Hesinger was saying the other day about Pepe's indentation.

47:30 You know, when you've written a test class, you're already three levels of indentation down before you've written any test code.

47:35 And you're going to go self.assert equal.

47:37 And there's also self.assert items equal if you just want to compare list items without the order.

47:43 And you've got self.assert is none.

47:45 And you've got assert multiline equal for strings.

47:47 And you've got assert rejects matches.

47:50 You've got assert – you know, like I can't even remember them, right?

47:53 Yeah.

47:54 And so you have to start looking at the docs whenever you're trying to compare two things.

47:58 And I think pytest is superior to that in which they just go, look, just say assert and then a thing.

48:03 And the test framework will figure out what the thing was you were asserting.

48:07 And it will try and give you a sensible error message without you having to be clever about it.

48:11 Yeah, that's fantastic.

48:11 And I really like that.

48:12 Just the assert keyword that you've seen before and a thing.

48:15 And other than that, you just put your tests in methods that start with test.

48:18 There's no need for a class unless you really want one.

48:20 Sure.

48:20 Very nice.

48:22 Well, I've been using unit tests.

48:24 Maybe I should be checking out pytest.

48:25 Yeah.

48:26 So you can run pytests on existing unit test tests.

48:29 Yeah.

48:30 And so there's a migration path there that will work.

48:32 And then the weird thing.

48:35 So the fact that the assert keyword, it will magically tell you what the two values were,

48:40 is the first bit of pytest magic that people raise their eyebrows at a little bit.

48:45 The really magic part is the way it does sort of set up and tear down.

48:49 Which is, you know, in unit tests, we write a methodical set up and a methodical tear down.

48:53 And that seems instinctive to us now because we're so used to it.

48:56 It's been beaten into us over the years.

48:58 But what we really want, and so that the pytest world is more kind of functional.

49:01 And what they say is, okay, well, if you want some setup to be done in a test,

49:06 you're going to define a method that does that setup.

49:07 Well, define a function that's going to do that.

49:10 So you define a function that says, like, prepare database, for example,

49:14 that's going to, like, set up a test database for you.

49:15 You do some stuff.

49:17 And then if that function is called prepare database, you put a decorator on it.

49:22 Say this is a fixture.

49:23 pytest's word for test setup stuff is a fixture.

49:27 Which is slightly different from the way Django uses the term, but bear with us.

49:31 Pop a decorator on it.

49:34 And then take any of the tests that need that fixture.

49:37 And then you just say, add an argument to that test.

49:39 Which, first of all, that function didn't have any arguments.

49:42 Now, you add an argument to that test.

49:43 And you just give that argument the same name as the function you'd find earlier.

49:45 And then when you run it, we'll magically find that function, execute it,

49:49 and inject it into your test for you.

49:50 That is magic.

49:51 That is magic.

49:52 Or a crazy convention.

49:53 Well, or a convention, right?

49:55 And, I mean, setup and teardown are kind of magic as well.

49:58 Like, there is something happening to make those happen.

50:00 Yeah, absolutely.

50:01 And so, like, is it any more explicit?

50:02 That's debatable.

50:03 I think it's just...

50:04 No, it sounds great to me.

50:05 But then you can have fixtures inheriting from fixtures.

50:08 So, if you have a fixture function called prepare database, maybe that inherits from prepare file system.

50:13 And so, similarly, you can give an argument to a fixture that's also another fixture.

50:17 And, you know, like, yeah, yeah.

50:19 It'll get...

50:21 It's like a Russian doll.

50:22 It'll get pretty fun pretty quickly.

50:23 Yeah, that's very cool.

50:24 So, do you discuss code coverage?

50:28 I don't, no.

50:30 It's a lacuna.

50:34 I guess we've never used it at work because we've got such a sort of religious adherence to TDD.

50:39 The guy next to you is the code coverage.

50:41 Well, they are.

50:42 And the methodology is in that, like, we basically don't allow ourselves to write any code in production that hasn't got a test.

50:47 So, you know, we've kind of assumed our coverage is 100%.

50:51 And so, it would be probably educational for us to actually run coverage one of these days.

50:57 But, no, I don't talk about it in the book.

50:59 I mention it at the end going, hey, here's the thing you should check out.

51:01 Yeah, here's the thing you should check out.

51:02 That's cool.

51:03 You know, you can't cover everything.

51:04 Yeah, no, of course.

51:05 You have to ship.

51:07 Even when it's a book, you have to ship at some point.

51:09 Yeah, yeah.

51:09 It's the trouble of anyone writing a book.

51:11 But, no, I do find that.

51:12 So, I talked about it being real.

51:14 In the book, we build a to-do list app.

51:16 So, we go ahead.

51:17 We learn how to database to-do list.

51:19 We start with a to-do list app that has, like, one item.

51:21 Then it has many items.

51:22 But it's the same list for everybody on earth.

51:24 And then there's, like, multiple lists for multiple people.

51:27 Great.

51:27 And then, like, once we've got that working, I go, okay.

51:30 Well, you've made a really ugly website.

51:31 Let's do some styling.

51:32 Because, like, it's not just about a Django view that returns horrible HTML.

51:36 Let's put Bootstrap on there and use CSS and make it look a bit presentable.

51:40 Which is something that, you know, most guys might not cover.

51:43 And then that's Chapter 7.

51:45 And then Chapter 8.

51:46 I'm like, right, good.

51:46 We've built a basic web light.

51:47 It's fine.

51:48 I know you can't delete to-do items.

51:49 You can't edit existing ones.

51:51 But that is a working to-do list app.

51:52 It's a minimum viable product.

51:53 So, now we need to ship it.

51:55 And so, like, Chapter 8 is deploy it to a server.

51:57 And I'm just going to go through how, like, now that you've got your tests, can you run them against a server?

52:02 Can they actually help you deploy as well?

52:04 And so, yeah, that gets even more real, I guess.

52:07 Yeah, very cool.

52:09 And a fairly fierce learning curve.

52:11 Yeah, it seems like a good place for people to start.

52:13 So, I'll put a link in the show to the book.

52:16 So, thank you.

52:17 Yeah, so you were talking about databases and dependencies.

52:20 And I'd like to come back to Python anyway to start a bit and talk about that a little bit more.

52:24 So, you guys have MySQL.

52:29 Sure.

52:29 Your Postgres.

52:30 Yeah.

52:30 Postgres.

52:30 And then I noticed something interesting, I think, in an email from you guys.

52:37 I think I'm remembering this, right?

52:39 So, now you're using containers.

52:40 Oh, yeah.

52:41 For your Postgres.

52:42 Sure.

52:43 Yeah.

52:43 So, is that Docker?

52:44 The Postgres ones are, yeah.

52:46 Yeah.

52:46 Yeah.

52:47 Yeah.

52:47 Well, so I guess anyone that's building a thing a little bit like what we're building eventually comes across containers.

52:52 Like, this is .cloud.

52:54 We're in a similar business and they invented Docker.

52:55 Yeah.

52:56 So, if you're running a lot of people's untrusted code on your servers, you've got to figure out a way of isolating them.

53:02 And the way you do that in Unix is with a bunch of cool tools that put together a tool these days,

53:07 containerization.

53:07 So, we've used bits and pieces of these tools everywhere.

53:10 And the thing with MySQL is the way we provide that is if you host a MySQL server, you can do multi-tenancy fairly easily.

53:22 You can create different user accounts for different users and you can say this user has permissions on this database and this user has permissions on that database and you're fine.

53:30 They're pretty well sandboxed from each other.

53:32 Postgres isn't so good in that respect.

53:36 It's not really designed with a multi-tenancy model in mind.

53:40 And pretty much in Postgres, unless you've got super user access to the server, you can't really do anything.

53:45 And none of the cool Postgres stuff is possible without being a super user.

53:50 So, you can't really do multi-tenancy Postgres.

53:54 So, we were forced to say, okay, well, then we can't just have one Postgres server that runs everyone with user accounts on the same server.

54:01 We're going to have to have multiple servers.

54:03 Everyone's going to have to effectively be a super user in there.

54:06 And a sensible way of doing that seemed to be to run each Postgres instance in some sort of container.

54:11 Yeah, that's really cool.

54:12 A virtual machine probably wouldn't be the right answer.

54:14 Yeah, too slow, right?

54:15 I mean, this is why everyone's using containers.

54:17 They're too expensive.

54:18 The density on the servers just isn't there.

54:20 Yeah.

54:21 If you're offering something for free, density matters.

54:23 Yeah.

54:23 Yeah.

54:24 Yeah.

54:24 So, that was nice.

54:26 So, that was where, yeah, we used Docker for the first time in production and we used Py.Test for the first time in production.

54:31 So, the Py.Test and Docker, like two experiments at the same time.

54:34 Terrible idea.

54:34 Great fun.

54:35 Sounds excellent.

54:36 And, yeah, so that's how that works.

54:38 We've been happy with it.

54:39 Uh-huh.

54:39 Cool.

54:40 And I saw on your features you're considering maybe sometime maybe was MongoDB.

54:47 Yeah.

54:48 Would that be a thing that might show up over there?

54:50 It might be.

54:50 I think we're looking in the short term to probably outsource that.

54:54 So, there's, I can't remember, there's a couple of companies out there that do MongoDB as a service.

55:00 Sure.

55:00 MongoHQ, MongoLab, ObjectRocket.

55:03 There you go.

55:04 All of these guys.

55:04 I think I'm going to say the three that come to my mind.

55:06 Well, I, you know, since we haven't settled on it, we won't big up any of them in particular today.

55:10 Yeah.

55:10 Because maybe they'll give us a good deal or something.

55:11 Yeah, exactly.

55:12 It's time for a bidding war.

55:13 Yeah.

55:15 So, I think what we do for Mongo maybe in the short term is pick one of those, try and build a bit of integration, just make it really easy for people to go, oh, okay, start a Mongo service.

55:22 And it will actually go out to, you know, whoever it will be.

55:24 Sure.

55:25 Create a user account on there.

55:26 And then, you know, wrap it up.

55:27 Just kind of delegate, wrap it up, make it amazing.

55:29 Yeah, that's cool.

55:30 And a lot of those guys are either on AWS or direct connect to AWS.

55:34 So, it would be relatively.

55:35 Yeah.

55:36 So, that's one of the fun things about Python Anywhere, actually, is if you ever do a Git clone of a massive repo and you're sitting there and it's going, okay, downloading 400 megabytes or more, not everything is fast on Python Anywhere.

55:51 But that is one of the things it is because it's in Amazon's data centers and GitHub's got some servers right next door.

55:56 Yeah.

55:56 When you get a repo, it comes down super fast.

55:59 Yeah.

56:00 Which is great.

56:00 Yeah.

56:01 I mean, other file system things aren't so fast because we have to have the challenge of running multiple servers but needing to give people access to the same file system no matter what server they're on.

56:10 You know, there's NFS in the background and that's not the fastest thing ever.

56:13 Yeah, of course.

56:14 But, yeah.

56:14 No, for doing internet stuff, being in a data center in the first place is great.

56:18 That's cool.

56:19 And that's how I get my source code onto the machines.

56:22 I just get, you know, get pull.

56:25 I've cloned it, set up my virtual environment, point it at the Git repo.

56:28 Yeah.

56:29 Yeah.

56:30 Is there a way to set up continuous delivery?

56:32 Yeah.

56:33 Yeah?

56:33 So you can, continuous delivery, so you can hack it a little bit.

56:37 Yeah, like with a web job to do a Git portal?

56:40 That sort of thing, yeah.

56:41 You could do that.

56:42 But you can, you can, you can set up, because like Python Anywhere is essentially a Linux server, you can set up a Git repository on it, one that you can push to.

56:55 So there's a, we've got a blog post about this, but you can set up a Git repository that will, that you can push to, set it up as a remote in your own local computers one.

57:03 And then you can do Git push Python Anywhere.

57:05 It'll arrive on Python Anywhere.

57:06 You can set up some hooks on Python Anywhere.

57:08 When they see new code coming in, maybe they'll even run your tests.

57:10 And then they can do a little thing that will like bounce your web workers and, and your website will be deployed.

57:16 Nice.

57:17 So you can, you can sort of hack it.

57:18 So we haven't built that in yet.

57:19 But you can, you can hack around a thing like that if you feel like it.

57:23 Yeah.

57:23 Cool.

57:24 Is that something you're considering?

57:26 Maybe, maybe not?

57:28 Well, we always have to think, you know, we have to serve, we have to serve the beginners and we have to serve the more advanced people.

57:34 Right.

57:34 And so the model is.

57:35 That what I'm describing is not very much in your original mission.

57:38 Right.

57:38 Yeah, yeah, yeah.

57:39 So like continuous deployment, right, as a thing is not the first thing, you know, it's not the first hurdle that people walk up to.

57:46 And so we like, we'd run, I think maybe for now we'd rather like say, can we make it easier for people to use virtual M's or can we make it easier for people to upgrade their version of Django?

57:55 If they're a beginner, we're like trying, trying to make that learning curve a bit smoother.

57:59 Yeah.

58:00 It seems like that kind of stuff would actually be way more broadly valuable.

58:04 Yeah.

58:04 I don't know.

58:05 It's different audiences, right?

58:06 Yeah.

58:07 Not necessarily to me because I'd like continuous integration as a button, but our continuous delivery.

58:11 But for most people will come.

58:13 It seems like that would be the right place to focus.

58:16 Yeah, yeah, yeah.

58:17 I mean, there's so many things.

58:19 It's hard to prioritize.

58:20 That's a good problem to have, right?

58:22 There's all this cool stuff you want to do and you got to pick.

58:27 Yeah, yeah.

58:28 So, you know, see what your users are asking for, right?

58:32 Yeah, IPython notebooks they want.

58:34 And we're trying to try to figure out what people are doing.

58:36 Oh, yeah, that would be cool.

58:36 Yeah, yeah, yeah.

58:37 I mean, it is.

58:38 You're getting IPython running in your local computer isn't totally straightforward.

58:41 It's not, especially on Windows because you've got some C dependency somewhere or whatever.

58:45 There are, there's anacondas.

58:46 Right, that's true.

58:47 Yeah, some of the prepackaged environments.

58:50 Before that, there was the M4 scientific Python distribution.

58:53 It's all the same problem.

58:55 Like, yeah, there's the things that should be easy that aren't.

58:57 And so, yeah, yeah.

58:59 We're going to see what we can do about it.

59:00 Yeah, so if you make that open web browser click button, that'd be fantastic.

59:04 Yeah, yeah, yeah.

59:05 Nice.

59:07 So, I think that's kind of getting to be a decent amount of stuff we've covered in the show.

59:12 Anything else you want to add?

59:14 Now, I promised myself I was going to say a thing and it's gone.

59:21 Let me ask you something else and maybe it'll sneak back into your subconscious.

59:24 So, one of the things I ask a lot of the guests on their way out the door is what is your sort of favorite package or library in Python?

59:31 Do you have some favorites?

59:33 You know when you type in pip install requirements.txt and it goes no package called this point requirements.txt?

59:41 Because you have to type in pip install dash r requirements.txt.

59:45 Yeah.

59:46 Right.

59:46 I've been trying for a little while to figure out if I can upload a package to PyPI called requirements.txt somehow.

59:53 So, that when you accidentally mistype pip install requirements.txt, it installs my package.

59:58 And because the setup.py is like, you know, completely unsecure.

01:00:02 It's just straight.

01:00:02 You can do whatever you want.

01:00:03 I was just going to open up Firefox to rickroll people.

01:00:09 So, that pip install requirements.txt would just rickroll you.

01:00:11 I think that would be great.

01:00:12 I think the PyPI guys have got there ahead of me on that.

01:00:16 So, it's not possible that I've found.

01:00:19 But I thought I'd throw that little evil idea out there in the world to the listeners of the podcast.

01:00:23 If you guys can figure it out, it would be hilarious.

01:00:25 That would be great.

01:00:25 Maybe slight misspellings of the word requirements.

01:00:28 Yes.

01:00:29 Get them like 10% of the time or 5% of the time.

01:00:32 Maybe requirements text without the dot.

01:00:34 Yes.

01:00:35 Right.

01:00:35 You could maybe catch a few people like that.

01:00:37 That's fantastic.

01:00:39 All right.

01:00:41 Final thoughts.

01:00:41 Have you thought of it?

01:00:42 I know.

01:00:43 That was it.

01:00:43 I think that was actually the rickroll thing.

01:00:44 That was the rickroll.

01:00:45 Awesome.

01:00:45 I must bring that up.

01:00:46 That's fine.

01:00:47 Yeah.

01:00:47 That's really good.

01:00:49 So, Harry, thank you so much for being on the show.

01:00:51 Yes.

01:00:52 It's really interesting.

01:00:53 I'm a huge fan of Python Anywhere.

01:00:55 If someone's out there listening and they're like, that sounds cool.

01:00:59 I want to check it out.

01:00:59 I want to play with this idea of a bash shell in my browser.

01:01:02 Whatever.

01:01:04 How do they get started?

01:01:06 So, pythonanywhere.com.

01:01:07 Python, P-O-I-T-H-O-N, anywhere, N-A-N-Y-W-H-E-R-E.

01:01:12 Or you can go to pythoneverywhere.com.

01:01:14 That redirects to pythonanywhere.com appropriately.

01:01:16 You can also go to python.org.

01:01:18 There's a little Python console on the front page there.

01:01:21 You can click the button.

01:01:22 You get a live console.

01:01:22 That's supplied by us if you feel like it.

01:01:25 And the other thing I have to plug or my editor will kill me.

01:01:28 I'm going to plug my book.

01:01:29 So, the book is available at obeythetestinggoat.com.

01:01:32 It's available both for free and for purchase.

01:01:35 So, the whole thing is available online for free for the zero pounds or dollars or anything.

01:01:41 But if you feel like buying it, you can as well.

01:01:43 And, yeah.

01:01:46 Those are the two websites that you have to go to.

01:01:48 pythonanywhere.com.

01:01:49 Obeythetestinggoat.com.

01:01:51 And your testing tutorial you did at PyCon is on YouTube, right?

01:01:57 Sure.

01:01:58 Yeah, yeah, yeah, yeah.

01:01:59 Is that just in the...

01:02:00 I think I actually have it in my list.

01:02:01 In one of the previous shows, I said, like, here are the essential presentations.

01:02:05 Yeah.

01:02:06 From PyCon 2015.

01:02:07 And I think it's in there.

01:02:08 But I'll put a direct link to it in the show as well.

01:02:10 For sure.

01:02:11 Yeah, yeah.

01:02:11 I mean, there's an O'Reilly official video you can buy.

01:02:14 Okay.

01:02:15 Maybe I'll link to that as well.

01:02:16 You can if you want.

01:02:17 But, you know, there are also free versions of all these things.

01:02:19 I'm no great believer in, you know, this is the internet.

01:02:22 This point is pretending that you can charge for digital things and that people won't find a way of getting them for free if they want them for free.

01:02:29 So I'm all about saying let's have them for free.

01:02:32 You know, your choice is between having it for free without your consent and having it for free with your consent.

01:02:37 And my choice is with my consent.

01:02:38 So help yourself to the stuff for free and pay for it if you feel like it.

01:02:41 Yeah, that's great.

01:02:42 I think people are more generous than a lot of businesses give them credit for.

01:02:47 And they're, you know, they'll say thanks and they'll buy something if it really helped them.

01:02:51 Well, so we're in danger of overstepping the end of the podcast here.

01:02:55 But I'm sort of a bit into internet activism.

01:02:59 I'm a member of the Pirate Party here in the UK.

01:03:01 And for me, it's worked very well.

01:03:04 Like I say, put my stuff online for free and people will pay for it.

01:03:06 And so I would love to expose that as an ideology.

01:03:09 I would say that it's a different calculus for me than it is for Stephen King.

01:03:18 If I put my book online for free, the people that read that, why are they reading a book about test-driven development for web development, right?

01:03:25 They're not reading that like to… It's not a scary… This is not a holiday airport thriller, right?

01:03:31 This is a thing they're reading.

01:03:32 They're reading because they want to get better at programming and they want to get better at programming because they're probably doing it for a job for money, right?

01:03:38 So I think people see the very act of reading that book as quite a commercial transaction.

01:03:42 And when I'm saying, hey, look, it's try before you buy.

01:03:45 Like, so read this.

01:03:46 If you get value out of it, you know, I'd love it if you paid.

01:03:48 I think people do go, well, I was reading this in the first place for monetary reasons, so I think I should probably pay.

01:03:53 Whereas, you know, like if Stephen King is sitting there putting all his books for free out there, you know, you're reading that.

01:03:59 You're not reading it for monetary reasons.

01:04:01 Your personal value of it is not the same as if it means a better job.

01:04:03 Exactly.

01:04:04 So maybe it's easier for me to upsell people to the paid version than it would be for Stephen King or something.

01:04:11 But yeah, no, absolutely.

01:04:11 It works for me.

01:04:12 That's cool.

01:04:13 Great.

01:04:13 All right.

01:04:13 Well, thank you again so much for being on the show.

01:04:15 It's really nice to meet you.

01:04:17 And I think it'll be a great conversation for everyone to listen to.

01:04:20 Great.

01:04:20 Thanks, Michael.

01:04:21 Yeah.

01:04:21 Bye.

01:04:22 Bye.

01:04:22 Bye.

01:04:22 Bye.

01:04:22 This has been another episode of Talk Python to Me.

01:04:27 Today's guest was Harry Percival.

01:04:29 Follow him on Twitter where he's at H-J-W-P.

01:04:33 This episode has been sponsored by CodeShip.

01:04:36 Please check them out at CodeShip.com and thank them on Twitter via at CodeShip.

01:04:41 Don't forget the discount code for listeners.

01:04:43 It's easy.

01:04:44 It's Talk Python, all caps, no spaces.

01:04:46 Remember, you can find the links from the show at Talk Python To Me.com slash episodes slash show slash 10.

01:04:54 And if you're feeling generous, check out our Patreon campaign at Patreon.com slash mkennedy.

01:05:01 Be sure to subscribe to the show.

01:05:03 Visit the website and choose subscribe in iTunes or grab the episode RSS feed and drop it into your favorite podcatcher.

01:05:09 You'll find both in the footer of every page.

01:05:12 This is your host, Michael Kennedy.

01:05:14 Thanks for listening.

01:05:15 Thanks for listening.

01:05:15 Bye.

01:05:16 Bye.

01:05:17 Bye.

01:05:17 Bye.

01:05:18 Bye.

01:05:19 Bye.

01:05:19 Bye.

01:05:20 Bye.

01:05:21 Bye.

01:05:22 Bye.

01:05:23 Bye.

01:05:24 best.

01:05:24 First developers.

01:05:26 First developers.

01:05:28 First developers.

01:05:29 First developers.

01:05:31 First developers.

01:05:32 First developers.

01:05:33 First developers.

01:05:35 Don't forget.

Back to show page
Talk Python's Mastodon Michael Kennedy's Mastodon