Brought to you by Michael and Brian - take a Talk Python course or get Brian's pytest book


Transcript #184: Too many ways to wait with await?

Return to episode page view on github
Recorded on Wednesday, May 27, 2020.

00:00 Hello and welcome to Python Bytes where we deliver Python news and headlines directly to your earbuds.

00:05 This is episode 184 recorded May 27th, 2020.

00:10 I'm Brian Okken.

00:11 And I'm Michael Kennedy.

00:12 And this episode is sponsored by DigitalOcean.

00:16 Thank you, DigitalOcean.

00:17 Yeah, thanks, DigitalOcean. Really appreciate it.

00:18 Well, I'm waiting, Michael.

00:20 You're waiting? What are you waiting for?

00:22 I'm waiting for the next AsyncIO story.

00:25 I guess it's my turn, isn't it?

00:27 Okay, sorry, let me see if I can get this right.

00:30 So the topic I want to talk about is waiting in async IO.

00:34 Yeah, so the magic of async IO, which was introduced in Python 3.4, never really appeared until Python 3.5 when the async and await keywords came into being, which let you write code that looks like standard single-threaded serial code, but actually is multi-threaded, or at least parallel concurrent to some degree.

00:56 depends on how you're running it, whether it's truly multi-threaded.

00:59 Anyway, there's a lot of options, let's say, on how you can interact with these coroutines and these tasks that are generated by the async I/O framework.

01:11 And anytime there's like four ways to do something in programming, you should be asking yourself, one, why are there four ways to do this?

01:20 But more importantly, when does way one apply best?

01:25 and what scenario should I use way three and what is the trade-off between two and four and so on, right?

01:31 So that's the case with async.io.

01:34 There's tons of ways to await things.

01:38 And Hank Henick, get the pronunciation right for me.

01:41 I know you got it.

01:42 You got it.

01:43 That's good.

01:43 Yeah.

01:44 Hank.

01:44 [laughs]

01:47 Sorry.

01:48 That's just a running thing.

01:49 I can never get it right.

01:50 I know.

01:50 Well, the problem is, I think I had it right.

01:53 And then we went back and forth so many times with so many variations.

01:56 Now I'm, it's broken.

01:58 sorry about messing up your name there.

02:00 So wrote a great article though, called waiting and async IO that does exactly that, that says, here are all the ways.

02:07 Here's the pluses and here's the minuses and the situations in which you apply them.

02:11 So if you're like serious about using async IO and you're building real things, basically this podcast episode is for you because I have this in another one that bring two really cool ideas together.

02:23 But let's talk about the waiting one first.

02:26 So it's really easy to start doing some work, right?

02:31 I can have two coroutines, let's say F and G, and I could say I want the result of F by saying, you know, result equals await calling F, and then result G equals await calling G.

02:44 And that's fine if what you're looking for is more concurrent execution of that part of code, right?

02:50 So this is say in a web method, like a view, someone makes a request, and there's not a lot you can do to make things go faster potentially for that one request, but you can say, let the server be less busy so it could handle like 10 or 20 times more of the same request.

03:07 So this real simple, like just a wait calling these functions, these async functions, it will allow your system to scale more, but it won't make things faster.

03:16 Like for example, if you're trying to crawl 20 web pages, this will not make it any faster.

03:21 It'll just make your code more complicated.

03:23 So don't do that, right?

03:24 So there's other ways in which you want to do that.

03:27 Another thing that I think a lot of people don't quite get is when you call one of these async functions, like async def function name, when you call it, it doesn't actually start it until you either await it or create a task from it.

03:43 So if you call like F and then G, and you think you're gonna come back and get to them later, and now they're running.

03:50 No, actually they're not unless you've created a task which starts them.

03:54 So you either have to await them, which blocks, or create these tasks to like kick them off.

03:59 That's pretty interesting, right?

04:00 Like that's not super obvious, I think.

04:01 Normally when you call a function, it does a thing.

04:04 But here, not so much.

04:05 So some other options, if you could call them both as create them as tasks, and then you could await those tasks, right?

04:11 Because their tasks are already running, and then you await them both, whichever one first.

04:15 Finishes first doesn't matter.

04:16 You wait till the first one's done, maybe the second one's already done.

04:19 So that's probably the pattern that most people are gonna be using.

04:23 But you can also use asyncIO gather that takes one or more awaitables as a star args, and then it waits for them all to finish, which is pretty cool.

04:33 And that itself is a future thing that you can await, right?

04:37 So you would say await asyncIO.gather.

04:40 - Oh, that's cool.

04:41 - Yeah, gather's awesome because I can create all these tasks and I just say, I just need them all to be done.

04:46 And when that's done, we can get the results and carry on.

04:48 And what's cool is when you await gather, you get a tuple of results.

04:51 So if I say async.io.gather function one, or task one, task two, then it returns the result one, comma, result two as a tuple.

05:01 So you can gather them up and get all the answers back, which is pretty cool.

05:04 - Yeah, that's really neat.

05:06 - Yeah, one of the problems with gather though, is you're saying I'm willing to wait forever for this to finish.

05:11 And sometimes that's fine, but sometimes things don't return correctly, or ever or in the right amount of time.

05:18 So you can use wait for, which is nice and allows you to pass a timeout.

05:23 But what's a little bit better than a wait for is there's an async timeout package on PyPI, which I'd not heard of.

05:29 And you can basically create a block that will, a with block that will timeout.

05:35 So you can say, I wanna have an async with timeout, five seconds, and then do a whole bunch of function calls and a waiting and all that.

05:42 And either they're all gonna finish or when five seconds passes, everything gets canceled that hasn't finished.

05:48 - Oh, that's cool.

05:49 - That's pretty cool, right?

05:50 Another one that's really interesting is I start a bunch of work, and then I would like to, say I kick off, I'm doing web scraping, and I wanna go get the results of 20 web pages.

05:59 I kick off 20 requests, and then I want to process them as they complete.

06:04 Like the first one that's done, I wanna work on that.

06:06 Then the next one, then the next one.

06:07 So you can create a task, or an iterable rather, from saying asyncio.ascompleted, and you give it a bunch of tasks, and it gives you an iterator that you can for in over that gives you the first completed one, then the second completed one, and just blocks until the next one is completed.

06:27 So you kick a bunch off, and then you just say for completed task in asyncio.ascompleted, and you give it your running tasks.

06:34 That's really slick, isn't it?

06:35 - That is slick.

06:36 Looks like it has a timeout also that you can add to it.

06:39 - Yeah, very nice.

06:41 - Yep, you can give it a timeout indeed.

06:43 Now, there's a few more things covered in there and I didn't go over the trade-offs too much.

06:49 You know, here's the scenario where you use this and that.

06:50 So if you really care about this, two things to do.

06:53 One is check out the article.

06:55 It's got a lot of details and each subsection has a little trade-offs.

06:59 Here's the good, here's the bad, which is nice.

07:01 And also you can check out my Async course, which talks about this and a whole bunch of other things on Async as well.

07:06 So I'll put a link in the show notes for that as well.

07:08 - Nice. - Yep.

07:09 So I was talking about waiting, you're talking about what, being faster?

07:13 That sounds better than just waiting around.

07:15 Yes, being faster.

07:17 Well, maybe even faster.

07:19 Not sure.

07:20 So I'm still on the fence.

07:21 Anyway, so virtual environments.

07:23 I use virtual environments.

07:24 Do you use virtual environments?

07:26 Anytime I have to install any, if pip install has to be typed, there's a virtual environment involved.

07:32 Yeah.

07:33 Yeah.

07:34 I use it for everything.

07:35 Even if I've got a machine, like a build machine that really only has one Python environment I'm only using it for one thing, I still set up a virtual environment.

07:41 It's just always.

07:42 And I've been, since the Python three started, Python three packaged VENV with Python.

07:49 So you can, you can create virtual environments just with the built in VENV package.

07:55 And I've been using that now before that was in there.

08:00 And if you were in Python two land, you needed to use the pip installable virtualenv package.

08:08 Now, it is still updated and it is still being maintained.

08:12 And I noticed, this was a conversation that started on Twitter this morning, that the virtual environment was still around and it was, maybe you should use that.

08:23 So I went and checked it out, again, the documentation for it, and it says, "Virtualenv is a tool to create isolated Python environments." We know this.

08:33 Since Python 3.3, I guess a subset of has been integrated into the standard library. Yep The V and V module does not offer all the features of this library Just to name some of the prominent ones V and V is slower and It's not extendable and it cannot create environments with multiple Python versions and you can't upstate it update it with pip, and it doesn't have a programmatic API.

09:02 Now, most of that, I just really don't care about.

09:05 But the slower part, I do care about.

09:08 So, I gave it a shot this morning. I used time, the time function on the command line just to time a couple of commands, created virtual environments with both VENV and virtualenv.

09:19 And yeah, VENV takes a little over two seconds, two and a half seconds To finish where is the virtual version takes like quite a bit under half a second.

09:30 So that's that's a lot and i mean if i'm doing a lot of virtual environments i might care.

09:36 Now one of the things i was like coming back and forth why why would i use bnv then if virtual environment virtual env is faster.

09:45 Will you have to install virtual and so.

09:48 I'll have to remember to do that i don't think i'll start teaching people this because it's just one more complication thing and a couple seconds in that big deal and i still like the prompt the dash dash prompt virtual and supports that too but it handles a different doesn't wrap your prompt in parentheses and and maybe it's just a nice city but i can like it i'm not sure i'm on the fence as to where i whether i should switcher.

10:14 or use it. To me it feels like I'm going to stick with VEMV.

10:18 For a long time I saw virtual EMV as just like it's legacy stuff. It's there because before Python 3.3 you didn't have VEMV built in so you're going to need it.

10:26 A lot of the tutorials talked about it and whatnot.

10:29 We recently covered it about why it got a big update and a lot of the things that it does that are nice and the speed is cool.

10:35 You know, maybe it wouldn't be that hard to adopt the --prompt dot feature, right? It's open source.

10:42 It could get a PR that does that.

10:44 That would be pretty cool, actually.

10:46 It probably should just so it's consistent.

10:48 But to me, the idea of having another thing I've got to install somewhere, probably into my user profiles Python packages, so that then I can then create virtual environments, so that I can then install things over into that area, it's just, it's fine for me.

11:03 But as somebody who does courses and teaching and other stuff like presentations, Like it just seems like, okay, you just lost how many people out of that, right?

11:13 Like, you know, what is the value?

11:15 Like you say, it's two seconds.

11:17 One of the things, what I would like to see, and it would be really nice, maybe that would even push me over the edge, is it drives me crazy that I create a new virtual environment from the latest version of Python that I can possibly get on the planet, and it tells me that pip is out of date.

11:32 - Now, virtual environment didn't do that for me this morning.

11:36 So it created a virtual environment with the newest pip in it.

11:40 Ooh, okay.

11:41 See now, that's pretty nice because it's annoying to say, okay, what you do is create this virtual environment and you pip install this thing.

11:47 Look, there's always going to be a warning.

11:49 So every single time what you're going to do is you're going to fix that warning by doing this.

11:53 Right, so if it grabs the latest, that's actually kind of cool now that I think of it.

11:57 I have a alias in my shell, my startup, that I just type V-E-N-V and it does the Python-MVNV, and then it does an upgrade of pip, and first it activates it, and then it does an upgrade of pip and setup tools, all in like four characters.

12:18 So that's what I've been doing these days.

12:20 - Yeah, I've got like a little snippet in my profile also that I'm using.

12:25 Funny enough, I shared it recently on Twitter, just my like two line snippet that I used, and then people kept on telling me to use all these other tools.

12:32 "Oh, you could just use this." Like, it's not just use this.

12:36 It's just a two-line snippet in a profile.

12:38 It's not a big deal.

12:39 - I don't even have to know what it is.

12:40 I just typed these three characters.

12:42 I'm good.

12:43 Why are you bothering me?

12:44 Why is this such a big deal?

12:45 I know, it's crazy.

12:46 - Yeah, yeah, anyway.

12:47 - What I would really like to see in none of these address is that something like, kind of like Node.js where it just has the virtual environment at the top level and it just walks up until it finds a virtual environment maybe complains if it doesn't, or it does something like that, right?

13:05 Like something to the effect where you say, here, I know that this is a feature, I forgot what it's called, it's like local Python or something like that, but it's not just built into Python.

13:14 So if I just went into that directory and tried to run it, it's not going to find and use that version of Python, you know?

13:20 Oh, well, the direnv, there's a few, there are a few packages that do that.

13:24 And that's one of the things that people are directing me to is direnv.

13:28 Direnv is cool.

13:28 We should talk about it as a separate item.

13:30 Yeah.

13:31 It's worth it.

13:31 But yeah, D-I-R-E-N-V is cool.

13:33 >> Yeah, we should talk about that sometime.

13:35 >> Yeah, yeah, yeah.

13:36 Don't use up all our items all on one show, man.

13:38 Come on.

13:39 >> Okay, let's thank our sponsor.

13:41 So DigitalOcean is sponsoring this episode.

13:44 And DigitalOcean just launched their Virtual Private Cloud and new trust platform.

13:50 Together, these make it easier to architect and run serious business applications with even stronger security and confidence.

13:56 The Virtual Private Cloud, or VPC, allows you to create multiple private networks for your account or your team instead of having just one private network.

14:05 DigitalOcean can auto-generate your private network's IP address range, or you can specify your own.

14:11 You can now configure droplets to behave as internet gateways.

14:15 Trust Platform is a new microsite provides you one place to get all your security and privacy questions answered, and download their available security certifications.

14:25 DigitalOcean is your trusted partner in the Cloud.

14:28 visit pythonbytes.fm/digitalocean to get a $100 credit for new users to build something awesome.

14:36 Yeah, awesome. Thanks for supporting the show, DigitalOcean. So before you had to wait on me, didn't you, Brian? It was frustrating.

14:42 I did have to wait.

14:43 All right. Let me tell you about when you might not even be awaiting stuff and things are still slow. So there's this cool analysis done by Chris Wellens in an article called Latency in asynchronous Python that I don't know if it talks about problems with async IO directly, but it's more talks about when you have a misconception of how something works over there, and then you apply a couple of patterns or behaviors to it, it might not do what you think. So for probably the best example would be there's, he gives a good one, there's a couple, I'll focus on this, this one where it's basically generating too much work and what can can be done about it.

15:22 So he says, I was debugging a program that was having some significant problems, but it was based on async IO, and it would eventually take really long time for network responses to come back.

15:36 And it's made of basically two parts.

15:38 One is this thing that has to send a little heartbeat or receive a heartbeat or something.

15:42 I don't remember if it's inbound or outbound, but it has to go beep, beep, beep, once every, let's say, millisecond, right?

15:49 So there's an async function and it just rips through and just every one millisecond it kicks off one of these heartbeats.

15:57 Totally simple, right?

15:58 You just say await asyncIO dot whatever, like sleep for one millisecond, then do the thing and then go on, right?

16:06 You can basically allow other concurrent work to happen while you're awaiting this sort of like timeout and to do it on a regular timeframe.

16:14 And then there's this other stuff that has to do some computational work that takes not very long like 10 milliseconds. So you're receiving a JSON request, you have to parse that JSON and do it like a little bit of work. So because async.io runs really on a single thread, that 10 milliseconds is going to block out and stop the heartbeat for 10 milliseconds. Which is, you know, whatever, it's fine.

16:38 It's like there's some variability but it's no big deal. However, if you run a whole bunch of these, in his example, Chris said let's run 200 of these computational things and like just start them up so that they can get put into this queue of work to be done.

16:52 Well, the way it works is it all gets scheduled.

16:54 It says, okay, we have a heartbeat and we have these 200 little slices of work.

16:58 Each of which is kind of take 10 milliseconds.

17:01 And there's a bunch of stuff around them that makes them a little bit slower, the scheduling and whatnot.

17:06 And then we have a bunch of more heartbeats.

17:08 So it goes beep, beep block for two seconds, beep, beep, beep, where you would expect, okay, I've got all these heartbeats going and I've got 200 little async things, let's like mix them up.

17:19 Right.

17:20 And like kind of share it fairly.

17:21 And it does not do that at all.

17:24 So he talks about basically what some of the challenges are there.

17:30 One is probably you shouldn't just give it that much work in some giant batch.

17:36 You should, you know, give it less work at a time, like some kind of like a work Q or you know, he said, let's see if we have similar for can work.

17:45 Now I don't remember if semaphores are reentrant or not.

17:48 It didn't work.

17:49 The semaphore didn't help at all.

17:51 Actually.

17:52 So we use a semaphore to limit limited 10, but if semaphores are reentrant, this is all one thread.

17:56 It doesn't matter.

17:57 Like the semaphore won't block itself.

17:59 So that's a, like this normal threading, locking and stuff like that.

18:04 They kind of don't apply.

18:05 Cause there's not actual threading going on.

18:06 So that doesn't really help, but he comes up with this example of.

18:11 that the async IO has a job queue, which allows you to push work into it and then you can like wait for it to be completed and there's all sorts of cool patterns and like producer consumer stuff that you can put on there.

18:23 So I actually put together an example.

18:24 He has like little code snippets.

18:26 I put together a running example and one whole program that demonstrates this and I have a link to the gist in the show notes.

18:33 And I also would like to just point out how much a fan of unsync I am, which I always talk about when I can around this async stuff Like, Unsync is a library that is 120 lines of Python and it unifies multiprocessing, async.io, threading, like all these different APIs into like a perfect thing that fits with async and await.

18:56 It's really, really nice.

18:57 But applying like the standard unsync adjustments to this code, to say like, what you do is just put a decorator @unsync on the function.

19:07 That's it.

19:08 you still use a wait, async and await and all that kind of stuff, the problem's gone.

19:13 Totally fixes it.

19:13 - Oh, really?

19:14 - Like, you don't have to go to the crazy queues and all that, like, the problem is gone.

19:17 It's fixed.

19:18 Well, it's alleviated.

19:20 It may still be like if you push it far enough under certain more complex criteria, but the example that showed the problem, you just make them unsync and you await them, it just runs like you would have originally expected.

19:32 Like, unsync is so beautiful.

19:34 - Oh, that's cool.

19:34 - It doesn't change the way async.io works.

19:37 It basically says, okay, the async work is going to run on a background thread, and this other computational stuff will fit into the API, but will technically run on its own thread.

19:46 So it's not like changing the internals, but you use the same code, and then now it doesn't have this problem because the way it slices them together is better, I think.

19:56 Anyway, it's pretty interesting. It's worth a look.

19:58 I also have a copy of that on the gist, and you can check that out and run it too.

20:01 That's pretty cool.

20:02 So, unsync allows you to possibly not think too much about whether you should have these things just be async or whether there should be threads or something.

20:11 It's really neat. It just cleans everything up.

20:15 I sure hope they don't deprecate it though.

20:17 Oh, that's a better transition.

20:19 I was going to say, speaking of cleaning things up.

20:22 That works too?

20:23 We'll just do both transitions.

20:25 So how to deprecate a PyPI package.

20:27 So you've put up a PyPI package and for some reason you don't want it to be up there.

20:33 I don't want a puppy anymore.

20:35 Why do I have to take care of this?

20:36 Yeah.

20:36 So there's lots of reasons why this might happen.

20:39 One of them might just be you accidentally, you didn't use the test IPI and use the live one and you put up foo or some variant of foo and you didn't mean to, maybe it's some other package that somebody took over and it's handling it better and you want people to use something else.

20:57 But anyway, there's lots of reasons why you might.

21:00 a guy named Paul McCann wrote a blog post about how to deprecate a PyPI package.

21:06 So he gives a few options, and I think these are cool.

21:10 One of the interesting things is he mentions is that PyPI doesn't really give you direction as to what it should look like, which one you should use. So he's giving his opinion, which is great.

21:20 You might use a deprecation warning.

21:23 And this doesn't really apply to entire packages, but let's say you've changed your API, so it might as well be listed here.

21:30 It's a good thing to, instead of just ripping out parts of your API, leave them in there, but make deprecation warnings in there.

21:37 They really should be errors instead of warnings, if you're really taking them out and just having the warning.

21:43 Something like an assert is probably better.

21:46 But there's a good thing to think about whether, don't just rip it out, maybe, I don't know.

21:50 But if you rip it out completely, assert will happen automatically, so maybe that's a good thing.

21:55 As far as packages though, you could just delete it so you can pipey I does allow you to remove packages I don't think that that's probably the right thing to do usually ever unless you just push something up and it was an accident then Deleting it is fine but if it's been up there for a while and people are using it deleting it has a problem that somebody else could take over the name and Possibly a malicious package could take over the name and start have people having install it. So there's problems with that so it's probably not a good choice most of the time.

22:27 The last two options are more reasonable.

22:30 There's a redirect shim.

22:32 This is an example, let's say there's an obvious package that is compatible that is being better maintained and you want to push people over to there.

22:42 If it's really very compatible, you can add a set of a shim that just, and there's some code examples here to just, if somebody installs it, it just installs the other package also I know what you want, we'll give you that one.

22:55 >> Yeah. Even having if somebody imports your package, it really just imports the other package too.

23:02 That's a little weird, but it is interesting that it's an option.

23:06 The thing I really like that probably the best is just a way to fail during install.

23:11 There's a code example here for if somebody installs something, and all the packaging works, but the install part will throw an error and you can put a message there redirecting people to use a different package or maybe just explain why you ripped this one out.

23:29 So I think I like the last one best.

23:32 So most of those are my commentary, but there's some options for how to deal with it.

23:36 So I thought that was good.

23:37 Yeah, I really like the sort of I tried to pip install it and it gives you instead of just failing or being gone.

23:44 It actually gives you a meaningful message like you should use this other package.

23:48 we're done. If you really intend to delete it, that's probably it.

23:51 Yeah, and one of the interesting things, the last couple, the redirect shim and the fail during install, those, he gives example packages that do this. And some of these are just mistyped things.

24:03 Like if people mistype something, maybe they meant something else.

24:08 And redirecting there.

24:10 Yeah, it seems so right only over at PyPI.

24:14 And you know if you make a mistake it's not good.

24:18 So knowing what to do. I mean people depend on it right? If you yank it out then it's trouble.

24:22 Yeah but if it's mistake driven though make sure you use the test interface first to play with things before you push garbage up there.

24:30 Also I'd really like people to not squat on names.

24:33 There's a lot of cool package names out there that really have nothing meaningful there because somebody decided they wanted to grab a name and then didn't do anything with it.

24:42 That's lame, don't do that.

24:43 - Yeah, that's definitely lame.

24:44 On the other hand, there are some times I'm like, how did you just get that name?

24:48 There'll be like a new package, like secure or something like that.

24:51 Like how did you get that after all this time, right?

24:54 It's crazy.

24:55 - Yeah, definitely.

24:56 - Yeah, yeah.

24:57 We're up to 236,000 packages.

25:00 That's pretty insane.

25:01 - Yeah.

25:02 - So Brian, would you like me to enlighten you a little bit and the listeners?

25:05 - Yes, please enlighten me.

25:07 - So last time you brought up a cool progress bar.

25:11 It was either last time or the time before, and it did all sorts of cool stuff.

25:15 But here's yet another one.

25:17 Again, an example of our listeners saying, oh, here's three cool things you talked about, but did you know there's these four others you've never heard of?

25:23 So Avram Lubkin sent over his progress bar package called Enlighten, and it's actually pretty cool.

25:32 Like there's a bunch of cool progress bars with nice animations and stuff, but there's a few features of Enlighten that might make you choose it.

25:40 One is you can have colored progress bars, which is nice, but more importantly, you can have multicolored progress bars.

25:47 So let me throw out an example that I think would connect for you, given that you're a fan of pytest.

25:52 Like if you run some sort of series or sequence of operations and you wanna show how far you're making them, but they have multiple outcomes like red is failure, green is success, and yellow is like skip or something like that.

26:04 You could have a progress bar that has three segments, a red segment, a yellow segment, and a green segment.

26:11 And it could be all one bar, but it could kind of like show you as it grows, here's the level of failure, here's the level of success, and so on.

26:19 All with color, 24-bit color, not just like eight colors either.

26:23 - Oh yeah, that'd be great.

26:24 That's cool. - Yeah, and then, and then I saw those just go off.

26:27 The other one is, a lot of these progress bars, they'll sort of control, they'll be rewriting the screen, right?

26:33 They'll be putting stuff across as it's happening.

26:35 But if you happen to do like a print statement, effectively writing the standard out or an exception that writes a standard error or something like that, it messes them all up.

26:46 So this one works well, even allows you to write print statements while it's working.

26:52 So the print statements kind of flow by above it, but it's whatever part of the screen it's taken over, it still is managing that as well.

26:59 So it overrides what print means or standard out and sends it where it belongs.

27:04 - That's cool.

27:04 That's pretty cool. It also automatically handles resizing except on Windows.

27:09 And where it says except on Windows, I'm not sure if that means on the new terminal, Windows terminal that they came out with that's much closer to what we have over on Mac and Linux.

27:19 Or if it just means it doesn't work on Windows at all. I suspect it might work on the new Windows terminal that just went 1.0, but certainly not on CMD.

27:27 Okay. Who uses CMD? Okay.

27:30 I mean that's what comes with Windows if you don't like go out of the way to get something right like commander or the new terminal or something like that.

27:37 Yeah but you gotta install git at least on Windows anyway and then you got bash that comes with it.

27:42 That's true.

27:43 So like all good things that have actions and behaviors and are visual there's a nice little animation even on the pypi.org page.

27:54 So if you go there, you can watch and actually see the stuff scrolling by.

27:57 It's like an animated GIF right on the PyPI page.

28:00 So very, very nice.

28:01 Well done.

28:01 You know, the multicolored progress bars, it does seem pretty awesome if that's your use case.

28:05 I want rainbow ones.

28:06 I want to do a rainbow.

28:08 Yes.

28:08 Maybe with like little unicorns just shooting out of it and just like all sorts of.

28:13 Yeah.

28:14 Sounds good.

28:14 Yes.

28:15 Stars and unicorns.

28:16 Yes.

28:17 It would be perfect.

28:17 Yeah.

28:18 Let's have that.

28:19 And people are starting to catch on that.

28:21 we like animations because they'll include it in the suggestion.

28:24 And by the way, it has an animation.

28:26 >> You can watch it here.

28:27 Yeah, good job.

28:27 >> Bringing it up.

28:28 Yeah.

28:30 >> You're part of it.

28:30 Awesome.

28:31 Well, nice work on that progress bar library.

28:33 It seems simple and well done.

28:34 >> Speaking of unicorns, I want to talk about oceans.

28:37 Wait, unicorns don't live in the ocean.

28:40 >> Mermaids.

28:41 >> Mermaids.

28:41 >> We'll just go with mermaids.

28:42 >> So I want to talk about code ocean.

28:44 So this was contributed by Daniel Mulkey.

28:48 So this is a pretty neat thing.

28:50 So Code Ocean is a paid service, but there's a free tier.

28:54 And it's a research collaboration platform that supports researchers from the beginning of a project through publication.

29:02 So this is kind of this neat thing.

29:04 I'm going to read a little bit from their About page.

29:07 We built a platform that can help give researchers back 20% of the time they spend troubleshooting technology in order to run and reproduce past work before completing new experiments.

29:18 and CodeOcean is an open access platform for code and data where users can develop, share, publish, and download code through a web browser, eliminating the need to install software, blah, blah, blah, blah.

29:30 Anyway, mission is to make research easier.

29:33 So this idea is you can have code snippets like Jupyter and Python and even things like MATLAB and C++ code running with the data in this kind of environment that you can collaborate with other people and just sort of build up these data sets and the science and the code and all bundled together.

29:55 And it's pretty cool. It also collaborates with some, one of the goals of it is to be able to have all of this reproducible code and data together in a form that's acceptable to journals. And one of the reasons why it was contributed is Daniel said that one of the peer-reviewed journals that he reads it happened to be SPIE's optical engineering journal, recommended this platform for associating code with the article.

30:23 So people trying to do science and be published, associating code ocean space with it is an option.

30:31 That's cool. And if it gets accepted by editors as, yeah, that's what you do, then it just makes it easier.

30:37 It's kind of like saying, oh, you have an open source project, what's the GitHub URL?

30:41 Not is it on GitHub, just where on GitHub is it?

30:44 I do technically know that there's GitLab and other places, but like most of the code that's on GitHub is what I was getting at, right?

30:50 [laughs]

30:51 Yeah.

30:52 Cool.

30:52 Well, this looks pretty neat.

30:53 I do think there's a lot of interesting takes on reproducibility in science, and that's definitely a good thing.

31:00 There's this, there's Binder, which is doing a lot of interesting stuff, although not as focused on exact reproducibility, but still nice.

31:10 There's Gigantum, which is also a cool platform for this kind of stuff.

31:14 So there's a lot of options and it's nice to see more of them like CodeOcean.

31:17 Yeah.

31:17 Nice.

31:18 Well, that's our six.

31:20 Do you have anything extra for us today?

31:22 I'm going to try to connect this to Python cause I want to be excited, cause I am excited about it.

31:27 How long has it been since astronauts have been launched into space?

31:31 And from, from NASA and from the U S like it's been a really long time, ever since the space shuttle got shut down four or five years ago, I heard it was like over 10 but I could have heard run. It's very possible. It's been a very long time. So today, I know this doesn't help you folks listening because the time it takes us to get this episode out, but hopefully this went well. But I'm super excited for SpaceX's launch in collaboration with NASA to send two astronauts up into space. Wow, are those guys brave to get onto one of these rockets. But also, So I think there's probably somewhere in the mix, a lot of Python in action.

32:10 If you go to SpaceX, they had, last time I looked at one random point, a couple months ago, they had 92 open positions for Python developers.

32:19 - Oh wow.

32:20 - I don't know if that's 92 people they're looking for, but at least there's 92 roles they were trying to fill.

32:25 There could be multiple people into any one role.

32:27 So that's a lot of Python.

32:29 And so somehow in this launch, there's got to be some interesting stories around Python.

32:34 And this is mostly to say, one, it's awesome that SpaceX and NASA are doing this.

32:39 Hopefully this goes well.

32:40 Lots and lots of luck to that.

32:41 But also, if anyone knows how to connect us with the people inside SpaceX doing awesome rocket stuff with Python, those would make great stories.

32:51 We would love to hear about those introductions and whatnot.

32:54 - Yeah, that would be cool.

32:55 I'd love to hear more about that.

32:57 Yeah, I do hope it goes well.

32:59 And I heard that possibly there was weather problems that might crop up, but we'll--

33:04 - Well, maybe people will get to watch this.

33:06 (both laughing)

33:07 - Not gonna let this happen.

33:08 - Maybe it'll be delayed for a week, we'll see.

33:10 Awesome, how about you, what do you got?

33:12 - I just downloaded 3.90 beta one, so Python 3.9 beta one is available for testing.

33:19 If you are maintaining a package or any other maintaining your application, you probably ought to download it and make sure your stuff works with 3.9.

33:27 - Oh yeah, that's cool, and because it's a beta now, it should be frozen in terms of features and APIs and stuff, right?

33:34 It's no longer changing.

33:36 So it's now time to start making sure your stuff works and yelling if it--

33:40 >>Yeah, right.

33:41 And another reason to download it is the prompt--

33:44 V and V with the prompt with the magic dot that turns your directory name.

33:50 Yeah, that is in 3.9.

33:51 >>Yeah, super cool.

33:52 Awesome.

33:53 Well, that's not very funny, but I could tell you something that is.

33:56 And it's very relevant to your item here, actually.

33:58 - Okay. - You ready for this?

33:59 So open up this link here and I'll put the link in the show notes 'cause this is a visual, I gotta describe it to you.

34:05 So this was sent over by Stephen Howell.

34:07 Thank you for that.

34:08 And this would be better during Halloween, but Halloween's far away, so we're gonna do it this way.

34:13 So there's a person standing around and there's a ghost standing behind them, right?

34:18 - Yeah. - The ghost says, "Boo!" Person doesn't react.

34:21 "Boo!" Person doesn't react.

34:23 "Boo!" Person doesn't react.

34:25 The person says, "Python 2.7, ah!" "Ahhh!" The person runs away.

34:30 [laughter]

34:32 Yeah, this is great.

34:33 It's good, right?

34:34 Yeah.

34:35 You got what it was about. What do you got here?

34:36 Well, I'm going to get haters for this, but I'm going to say it anyway.

34:39 So, somebody named Bert sent us a meta joke, because we have used PyJokes before.

34:45 We love PyJokes.

34:46 And I'm going to modify it a little bit.

34:48 So, what does PyJokes have in common with Java?

34:50 It gets updated all the time, but never gets any better.

34:54 [laughter]

34:55 That's pretty funny.

34:56 I don't even really use Java, but I have a Java tool on my desktop.

35:00 And so I get like, "Java's updated. Do you want to do the update?" All the time.

35:04 Make it stop.

35:06 Yeah, that's funny.

35:08 Yeah, PyJokes is good.

35:09 If you all need some programming jokes, just pip install --user pyjokes.

35:13 And then you can type "pyjoke" anytime you want.

35:15 Yeah.

35:16 I had to change it because the original joke was like about Flash, Adobe Flash.

35:21 And who has that? Is that even a thing anymore?

35:24 Yeah, I don't even think it gets updated anymore.

35:26 I don't know, maybe it does.

35:27 I sure hope it's not on my computer.

35:29 Yeah.

35:30 It's a security flaw.

35:31 Yeah, it totally is.

35:32 Awesome.

35:33 All right, well, very funny.

35:34 All right.

35:35 Thank you.

35:36 Yep, you bet.

35:37 Bye-bye.

35:38 Thank you for listening to Python Bytes.

35:39 Follow the show on Twitter @pythonbytes.

35:41 That's Python Bytes as in B-Y-T-E-S.

35:44 And get the full show notes at pythonbytes.fm.

35:47 If you have a news item you want featured, just visit pythonbytes.fm and send it our way.

35:53 out for sharing something cool. This is Brian Okken and on behalf of myself and Michael Kennedy, thank you for listening and sharing this podcast with your friends and colleagues.

Back to show page