Python Bytes - #184 Too many ways to wait with await?

Episode Date: June 5, 2020

Topics covered in this episode: Waiting in asyncio virtualenv is faster than venv Latency in Asynchronous Python How to Deprecate a PyPI Package Another progress bar library: Enlighten Code Ocean E...xtras Joke See the full show notes for this episode on the website at pythonbytes.fm/184

Transcript
Discussion (0)
Starting point is 00:00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds. This is episode 184, recorded May 27th, 2020. I'm Brian Ocken. And I'm Michael Kennedy. And this episode is sponsored by DigitalOcean. Thank you, DigitalOcean. Yeah, thanks, DigitalOcean. Really appreciate it. Well, I'm waiting, Michael.
Starting point is 00:00:20 You're waiting? What are you waiting for? I'm waiting for the next AsyncIO story. I guess it's my turn, isn't it? Okay. Sorry, let me see if I can get this right. So the topic I want to talk about is waiting in AsyncIO. Yeah, so the magic of AsyncIO, 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
Starting point is 00:00:47 write code that looks like standard single-threaded serial code, but actually is multi-threaded, or at least parallel concurrent to some degree. Depends on how you're running it, whether it's truly multi-threaded. Anyway, there's a lot of options, let's say, on how you can interact with these co-routines and these tasks that are generated by the AsyncIO framework. 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? But more importantly, when does way one apply best? And what scenario should i use way three and what is the trade-off between two and four and so on right so that's the case with async io there's tons of ways to wait or await things and hank hennick get the pronunciation right for me
Starting point is 00:01:41 i know you got it you got it that's good yeah hank sorry that's just a running thing i can never get i know well i'm the problem is i think i had it right and then we went back and forth so many times with so many variations now i'm i'm it's broken uh sorry about mess up your name there so i wrote a great article though called waiting in async io that does exactly that that says here are the ways, here's the pluses and here's the minuses and the situations in which you apply them. 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 and another one that bring two really cool ideas together. But let's talk about the waiting one first. So it's really easy to start doing some work, right? 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
Starting point is 00:02:38 a wait calling F and then result G equals a wait calling. And that's fine. If what you're looking for is more concurrent execution of that part of code, right? 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 requests, right? So this real simple, like just a weight calling these functions, these async functions, it will allow your system to scale more, but it won't make things faster. Like for example, if you're trying to crawl 20 web pages, this will not make it any faster. It'll
Starting point is 00:03:22 just make your code more complicated. So don't do right so there's other ways which you want to do that 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. So if you call like F and then G, and you think you're going to come back and get to them later, now they're running. No, actually they're not, unless you've created a task, which starts them. So you either have to await them, which blocks,
Starting point is 00:03:57 or create these tasks to like kick them off. That's pretty interesting, right? Like that's not super obvious, I think. Normally when you call a function, it does a thing. But here, not so much. So some other options, if you could call them both as create them as tasks, and then you could await those tasks, right? Because they are tasks are already running. And then you await them both, whichever one first finished first doesn't matter. You wait till the first one's done and maybe the second one's already done. So that's probably the pattern
Starting point is 00:04:21 that most people are going to be using, 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. And that itself is a future thing that you can await, right? So you would say await asyncIO.gather. Oh, that's cool. Yeah, gather is awesome because I can create all these tasks. I just need them all to be done. And when that's done, we can get the results and carry on.
Starting point is 00:04:47 And what's cool is when you await Gather, you get a tuple of results. So if I say asyncIO gather function one, or task one, task two, then it returns the result one comma result two as a tuple. So you can gather them up and get all the answers back, which is pretty cool. Yeah, that's really neat.
Starting point is 00:05:06 Yeah. One of the problems with gather though, is you're saying I'm willing to wait forever for this to finish. And sometimes that's fine, but sometimes things don't return correctly or ever or in the right amount of time. So you can use wait for, which is nice and allows you to pass a timeout. 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. And you can basically create a block that will, a with block that will timeout.
Starting point is 00:05:35 So you can say, I want to have an async with timeout five seconds and then do a whole bunch of function calls and a waiting and all that. And either they're all going to finish or when five seconds passes, everything gets canceled that hasn't finished. Oh, that's cool. That's pretty cool, right? Another one that's really interesting is I start a bunch of work
Starting point is 00:05:52 and then I would like to say I kick off, I'm doing web scraping and I want to go get the results of 20 web pages. I kick off 20 requests and then I want to process them as they complete. Like the first one that's done i want to work on that then the next one then the next one so you can create a task or an iterable rather from saying async io dot as completed and you give it a bunch of tasks and it gives you an iterator that you can four in over that gives you the first completed one then the second completed one and just blocks until the next one is completed. So you kick a bunch off,
Starting point is 00:06:28 and then you just say for completed task in asyncio as completed, and you give it your running task. That's really slick, isn't it? That is slick. Looks like it has a timeout also that you can add to it. Yeah, very nice. Yep, you can give it a timeout indeed.
Starting point is 00:06:43 Now, there's a few more things covered in there, and I didn't go over the trade-offs too much. You know, here's the scenario is this and that. So if you really care about this, two things to do. One is check out the article. It's got a lot of details and each subsection has a little trade-offs. Here's the good, here's the bad, which is nice. And also you can check out my async course, which talks about this and a whole bunch of other things on async as well.
Starting point is 00:07:06 So I'll put a link in the show notes for that as well. Nice. Yep. So I was talking about waiting. You're talking about what, being faster? That sounds better than just waiting around. Yes, being faster. Well, maybe being faster.
Starting point is 00:07:19 I'm not sure. So I'm still on the fence. Anyway, so virtual environments. I use virtual environments. Do you use virtual environments? Anytime I have to install any, if pip install has to be typed, there's a virtual environment involved, yeah.
Starting point is 00:07:31 Yeah, I use it for everything. Even if I've got a machine, like a build machine, that really only has one Python environment and I'm only using it for one thing, I still set up a virtual environment. It's just always. And I've been, since the Python 3 started, Python 3 packaged VENV with Python. So you can create virtual environments just with the built
Starting point is 00:07:53 in VENV package. And I've been using that. Now, before that was in there, and if you were in Python 2 land, you needed to use the pip installable virtual env package. Now, it is still updated and it is still being maintained. 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. So I went and checked it out again the documentation for it and it says uh virtual env is a tool tool to create isolated python environments we know this since python 3.3 i guess a subset of has been integrated into the standard library yep the vnv module does not offer all the features of this library. Just to name some of the prominent ones,
Starting point is 00:08:47 VNV is slower and it's not extendable and it cannot create environments with multiple Python versions and you can't update it with pip and it doesn't have a programmatic API. Now most of that I just really don't care about. But the slower part I do care about. 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. And, yeah, VENV takes a little over two seconds, two and a half seconds to finish, whereas the virtual env version takes like quite a bit under half a second.
Starting point is 00:09:33 So that's a lot. And I mean, if I'm doing a lot of virtual environments, I might care. Now, one of the things I was like coming back and forth, why would I use VENV then if virtual environment, virtual env is faster? Well, you have to pip install virtual env. And so 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 of seconds isn't that big of a deal. And I still like the prompt, the dash dash prompt.
Starting point is 00:10:04 Virtual env supports that too, but it handles it different. It doesn't wrap your prompt in parentheses. And maybe that's just a nicety, but I kind of like it. I'm not sure. I'm on the fence as to whether I should switch or use it. To me, it feels like I'm going to stick with VEMV. 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 vmv built in so you're going to need it a lot of the tutorials talked about it and whatnot 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 you know maybe it wouldn't be that hard for to adopt the dash dash prompt dot feature right
Starting point is 00:10:41 it's open source right it could get a pr that does that. That would be pretty cool, actually. It probably should just so it's consistent. 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.
Starting point is 00:11:02 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 like you know what is the value like you say it's two seconds 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.
Starting point is 00:11:31 And it tells me that pip is out of date. Now, virtual environment didn't do that for me this morning. So it created a virtual environment with the newest pip in it. Oh, okay. 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. Oh, look, there's always going to be a it. Ooh, okay. See, now that's pretty nice because it's annoying to say, okay, what you do is create this virtual environment
Starting point is 00:11:45 and you pip install this thing. Look, there's always going to be a warning. So every single time what you're going to do is you're going to fix that warning by doing this. Right.
Starting point is 00:11:54 So if it grabs the latest, that's actually kind of cool now that I think of it. I have a alias in my shell, my startup, that I just type V-E-N-V and it does the Python-M-V mv and v 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
Starting point is 00:12:16 like four characters so that's what i've been doing these days yeah i've got like a little snippet in my profile also that I'm using. Funny enough, I shared it recently on Twitter, just my two-line snippet that I used. And then people kept on telling me to use all these other tools. Oh, you could just use this. It's not just use this. It's just a two-line snippet in a profile. It's not a big deal.
Starting point is 00:12:40 I don't even have to know what it is. I just typed these three characters. I'm good. Why are you bothering me? Why is this such a big deal? I know, it's i just typed these three characters i'm good why are you bothering me right why is it such a big deal i know it's crazy yeah yeah 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 the virtual environment and maybe complains if it doesn't or it it does something like that, right? Like something to the effect where you say,
Starting point is 00:13:08 I know that this is a feature, I forgot what it's called, it's like the local Python or something like that, but it's not just built into Python. 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. Oh, well, the dirinv,
Starting point is 00:13:22 there are a few packages that do that. And that's one of the things that people are directing me to is Durinv. Durinv is cool. We should talk about it as a separate item. It's worth it. But yeah, D-I-R-E-N-V is cool. Yeah, we should talk about that sometime. Yeah, yeah, yeah. Don't use up all our items all on one show, man. Come on. Okay, let's thank our sponsor. So DigitalOcean is sponsoring this episode. And DigitalOcean just launched their virtual private cloud and new trust platform. Together, these make it easier to architect and run serious business applications with even stronger security and confidence. 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.
Starting point is 00:14:10 DigitalOcean can auto-generate your private network's IP address range, or you can specify your own. You can now configure droplets to behave as internet gateways. And Trust Platform as a new microsite provides you one place to get all your security and privacy questions answered and download their available security certifications. DigitalOcean is your trusted partner in the cloud. Visit pythonbytes.fm slash DigitalOcean to get a $100 credit for new users to build something awesome. Yeah, awesome. Thanks for supporting the show, DigitalOcean. So before you had to wait on me, didn't you, Brian?
Starting point is 00:14:41 It was frustrating. I did have to wait. 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
Starting point is 00:15:12 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 be done about it. 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. And it's made of basically two parts. One is this thing that has to send a little heartbeat or receive a heartbeat or something. I don't remember if it's inbound or outbound, but it has to go beep, beep once every let's say millisecond right so there's an async function and it just rips through and just every one millisecond it kicks off one of these heartbeats totally simple right you just say await async io dot whatever like sleep for one
Starting point is 00:16:03 millisecond then do the thing and then then go on, right? 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. 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 like a little bit of work right so because async io runs really on a single thread that 10 milliseconds is going to block out and stop the heartbeat for for 10 milliseconds which is you know whatever it's fine it's like there's some little bit of variability but it's no big deal however if you run a whole bunch of
Starting point is 00:16:43 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 well the way it works is it all gets scheduled it says okay we have a heartbeat and we have these 200 little slices of work each of which is kind of take 10 milliseconds and there's a bunch of stuff around them that makes them a little bit slower the scheduling and whatnot and then we have a bunch of more heartbeats 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 right like kind of share it fairly and it does not do that at all. So he talks about basically
Starting point is 00:17:27 what some of the challenges are there. One is probably you shouldn't just give it that much work in some giant batch. You should, you know, give it less work at a time, like some kind of like work queue or, you know, he said, let's see if a semaphore can work. Now, I don't remember if semaphores are reentrant or not. It didn't work. The semaphore didn't help at all, actually. He said we can use a semaphore to limit it to 10. But if semaphores are reentrant, this is all one thread.
Starting point is 00:17:56 It doesn't matter. Like the semaphore won't block itself. So that's like this normal threading, locking, and stuff like that. They kind of don't apply because there's not actual threading going on. So that doesn't really help. But he comes up with this example of 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.
Starting point is 00:18:22 So I actually put together an example. He has like little code snippets. 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. 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
Starting point is 00:18:40 around this Async stuff. Like Unsync is a library that is 128 lines of Python and it unifies multi-processing async io threading thread like the all these different apis into like a perfect thing that fits with async in a way it's really really nice but applying like the standard unsync adjustments to this code to say like what you do is just put a decorator at unsync on the function that's it you still use a weight and async and a weight and all that kind of stuff the problem is gone totally fixes it oh really like you don't have to go to like crazy queues
Starting point is 00:19:16 and all that like the problem is gone it's it's fixed well it's alleviated it may still be like if you push it far enough under certain like more complex criteria but the example that showed the problem you just make them unsync and you await them and it just runs like you would have originally expected like unsync is so beautiful that's cool it doesn't change the way async io works 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 so it's it's not like changing the internals but you use the same code and then now this doesn't have this problem because the way it slices them together is better i think anyway
Starting point is 00:19:56 it's pretty interesting it's worth a look also i have a copy of that on the gist and you can check that out and run it too that's pretty cool 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. It's really neat. It just cleans everything up, but I sure hope they don't deprecate it though. Oh, that's a better transition. I was going to say, speaking of cleaning things up, but we'll just do both transitions. So how to deprecate a PyPI package. So you've put up a PyPI package and for some reason you don't want it to be up there. I don't want a puppy anymore.
Starting point is 00:20:35 Why do I have to take care of this? Yeah. So there's lots of reasons why this might happen. One of them might just be you accidentally, you didn't use the test PyPI 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 but anyway there's lots of reasons why you might a guy named paul mccann wrote a blog post about how to deprecate a PyPI package. So he gives a few options, and I think these are cool.
Starting point is 00:21:10 One of the interesting things, as he mentions, is the 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. You might use a deprecation warning. 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. It's a good thing to, instead of just ripping out parts of your API,
Starting point is 00:21:34 leave them in there, but make deprecation warnings in there. They really should be errors instead of warnings. If you're really taking them out and just having the warning, something like an assert is probably better. But there is a good thing to think about whether don't just rip it out, maybe.
Starting point is 00:21:50 I don't know. But if you rip it out completely, the assert will happen automatically. So maybe that's a good thing. As far as packages, though, you could just delete it. So you can, PyPI does allow you to remove packages. I don't think that that's probably
Starting point is 00:22:03 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 the last two options are more reasonable there's a redirect shim so this is an example like 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 if it's really very
Starting point is 00:22:43 compatible you can add a setup, a shim that just, and there's some code examples here to just, if somebody installs it, it just installs the other package also that people should be using. I know what you want, we'll give you that one. Yeah. And even having, if somebody imports your package,
Starting point is 00:22:59 it really just imports the other package too. That's a little weird, but it is interesting that it's an option. The thing I really like that probably the best is just a way to fail during install. And there's a code example here for if somebody at PIV installs something and all the packaging works,
Starting point is 00:23:18 but the install part will throw a 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 so i think i like the last one best so most of those are my commentary but there's some options for how to deal with it so i thought that was good yeah i really like the sort of i tried to pip install it and it gives you instead of just failing or being gone it actually gives you a meaningful message. Like, you should use this other package.
Starting point is 00:23:48 We're done. If you really intend to delete it, that's probably it. Yeah, and one of the interesting things, the last couple, the redirect shim and the fail during install, he gives example packages that do this. And some of these are just mistyped things. Like, if people mistype something try they maybe they meant something else and and uh redirecting there yeah it seems so right only over at pipey
Starting point is 00:24:13 i and you know if uh you make a mistake it's it's not good so knowing what to do i mean people depend on it right if you yank it out then it's trouble 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 there's also i'd really like people to not squat on names 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 yeah didn't do anything with it that's lame don't do that yeah that's definitely lame on the other hand there are some times I'm like, how did you just get that name? There'll be like a new package, like secure or something like that.
Starting point is 00:24:51 Like, how did you get that after all this time? Right. It's crazy. Yeah, definitely. Yeah. Yeah. Or up to 236,000 packages. That's pretty insane. Yeah. So Brian, would you like me to enlighten you a little bit and the listeners? Yes, please enlighten me. So last time you brought up a cool progress bar, it was either the last time or the time before, and it did all sorts of cool stuff. But here's yet another one.
Starting point is 00:25:17 Again, an example of our listeners saying, oh, here's three cool things you talked about, but did you know there are these four others you've never heard of? Yeah. things you talked about but did you know there's these four others you've never heard of yeah so avram lubkin sent over his progress bar package called enlighten and it's actually pretty cool like there's a bunch of cool progress bars with nice animations and stuff but there's a few features of enlightened that might make you choose it one is you can have colored progress bars which is nice but more importantly you can have multi- bars, which is nice, but more importantly, you can have multicolored progress bars. So let me throw out an example that I think would connect for you, given that you're a fan of PyTest.
Starting point is 00:25:52 Like if you run some sort of series or sequence of operations and you want to show how far you're making it, but they have multiple outcomes like red is failure, green is success, and yellow is like skip or something like that you could have a progress bar that has three segments a red segment a yellow segment and a green segment and they could 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 all with color 224 bit color not just like eight colors either oh yeah that'd be great. That's good. And the nice thing is those just go off. The other one is a lot of these progress bars,
Starting point is 00:26:30 they'll sort of control, they'll be rewriting the screen, right? They'll be putting stuff across as it's happening. But if you happen to do like a print statement, effectively writing a standard out or an exception that writes a standard error or something like that, you know messes them all up right so this one works well even allows you to write print statements while it's working so the print statements kind of flow by above it but it's you know whatever part of the screen it's taken over it still is managing that as well so it overrides what print means or standard out
Starting point is 00:27:01 and sends it where it belongs that's cool yeah that's pretty cool it also automatically handles resizing except on windows 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 or if it just means it doesn't work on windows at all i suspect it it might work on the new windows terminal that just got went 1.0 but certainly not on cmd okay who uses cmd okay 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 yeah but you gotta install git at least on windows anyway and then you got bash yeah it comes with it so that's true so like all good things that
Starting point is 00:27:46 have actions and behaviors and are visual there's a nice little animation even on the pi pi.org page so if you go there you can watch and actually see the the stuff scrolling by it's like an animated gif right on the pi pi page so very very nice well done you know the multi-colored progress bars it does seem pretty awesome if that's your use case i want rainbow ones i want to do a rainbow yes maybe with like little unicorns just shooting out of it and just like all sorts of crit yeah sounds good yes stars and unicorns yes it would be perfect yeah let's have that and people are starting to catch on that we like animations because they'll include it in the suggestion and by the way it has an animation because watch it here yeah good job bringing it up yeah you're part of it awesome well nice work on that progress bar library it seems simple and
Starting point is 00:28:34 well done speaking of unicorns i want to talk about oceans wait unicorns don't live in the ocean mermaids mermaids mermaids so i talk about CodeOcean. So this was contributed by Daniel Mulkey. So this is a pretty neat thing. So CodeOcean is a paid service, but there's a free tier. And it's a research collaboration platform that supports researchers from the beginning of a project through publication. So this is kind of this neat thing. I'm going to read a little bit from their about page. We built a platform that can help give researchers back 20% of the time they spend troubleshooting
Starting point is 00:29:12 technology in order to run and reproduce past work before completing new experiments. 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 anyway uh mission is to make research easier so this idea is you can have like code snippets like uh jupiter 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. And it's pretty cool. It also collaborates with some, one of the
Starting point is 00:30:00 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 your article so if people trying to be do science and be published associating a code ocean space with it is an option that's cool and if it gets accepted by editors as yeah that's what you do then it just makes it easier like it's kind of like saying oh you have an open source project what's the github url all right not is it on github just where on GitHub is it? Yeah. I do technically know that there's GitLab and other places, but like most of the code lives on GitHub is what I was getting at.
Starting point is 00:30:50 Right? Yeah. Cool. Well, this looks pretty neat. I do think there's a lot of interesting takes on reproducibility in science, and that's definitely a good thing. There's this,
Starting point is 00:31:01 there's binder, which is doing a lot of interesting stuff, although not as focused on exact reproducibility, but still nice. There's Gigantum, which is also a cool platform for this kind of stuff. So there's a lot of options and it's nice to see more of them like CodeOcean.
Starting point is 00:31:17 Yeah, nice. Well, that's our six. Do you have anything extra for us today? I'm going to try to connect this to Python because I am excited about it. How long has it been since astronauts have been launched into space from NASA and from the U.S.? 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.
Starting point is 00:31:42 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 on to one of these rockets and but also i think there's probably somewhere in the mix a lot of python in action 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 oh wow i don't
Starting point is 00:32:19 know if that's 92 people they're looking for but at least there's 92 roles they were trying to fill. There could be multiple people into any one role. So that's a lot of Python. And so somehow in this launch, there's got to be some interesting stories around Python. And this is mostly to say, one, it's awesome that SpaceX and NASA are doing this. Hopefully this goes well.
Starting point is 00:32:41 Lots and lots of luck to that. 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 we would love to hear about those and introductions and whatnot yeah that would be cool i'd love to hear more about that yeah i do hope it goes well later and i heard that possibly there was weather problems that might crop up but well well maybe people will get to watch this. Knock on wood. Maybe it'll be delayed for a week. We'll see.
Starting point is 00:33:10 Awesome. How about you? What do you got? I just downloaded 3.90 beta 1. So Python 3.9 beta 1 is available for testing. 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. Oh, yeah, that's cool.
Starting point is 00:33:28 And because it's a beta now, it should be frozen in terms of features and APIs and stuff, right? It's no longer changing. So it's now time to start making sure your stuff works and yelling if it doesn't. Yeah, right. And another reason to download it is the prompt, virtual VNV with the prompt, virtual V and V
Starting point is 00:33:45 with the prompt with the magic dot that turns your directory name. Yeah, that is in 3.9. Yeah, super cool. Awesome. Well, that's not very funny, but I could tell you
Starting point is 00:33:55 something that is. And it's very relevant to your item here, actually. Okay. You ready for this? So open up this link here and I'll put the link in the show notes
Starting point is 00:34:03 because this is a visual I got to describe it to you. So this was sent over by steven howell thank you for that and this would be better during halloween but halloween's far away so we're gonna do it this way so there's a person standing around and there's a ghost standing behind them right yeah the ghost says boo person doesn't react boo person doesn't react boo person doesn't react. Boo. Person doesn't react. Boo. Person doesn't react. The person says, Python 2.7. Ah, the person runs away. Yeah, this is great.
Starting point is 00:34:33 It's good, right? Yeah. You got what it was as well. What do you got here? Well, I'm going to get haters for this, but I'm going to say it anyway. So somebody named Bert sent us a meta joke because we have used PyJokes before. We love PyJokes. And I'm going to modify it a little bit.
Starting point is 00:34:47 So what does PyJokes have in common with Java? It gets updated all the time but never gets any better. That's pretty funny. I don't even really use Java, but I have a Java tool on my desktop. And so I get like, Java's updated. Do you want to do the update? All the time. Make it stop
Starting point is 00:35:05 yeah yeah that's funny yeah pyjokes is good if you all need some programming jokes just pip install dash user pyjokes and then you can type by joke anytime you want yeah i had to change it because the original joke was like about flash adobe flash and who has that is that even a thing anymore yeah i don't even think it gets updated anymore. I don't know. Maybe it does. I sure hope it's not on my computer. Yeah.
Starting point is 00:35:30 It's a security flaw. Yeah, it totally is. Awesome. All right. Well, very funny. All right. Thank you. Yep, you bet.
Starting point is 00:35:36 Bye-bye. Thank you for listening to Python Bytes. Follow the show on Twitter at Python Bytes. That's Python Bytes as in B-Y-T-E-S. And get the full show notes at pythonbytes. That's Python Bytes as in B-Y-T-E-S. And get the full show notes at PythonBytes.fm. If you have a news item you want featured, just visit PythonBytes.fm and send it our way. We're always on the lookout for sharing something cool. This is Brian Ocken, and on behalf of myself and Michael Kennedy, thank you for listening and sharing this podcast with your
Starting point is 00:36:00 friends and colleagues.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.