 Welcome back everyone. My name is Brian and we're going to continue our journey into Python. We're going to talk about queues in futures. Now, what is a queue and what is a future? This is a little confusing here, but really what we're talking about is getting a return value from a thread. So far, we've been doing threading and it really hasn't returned anything back to us, and that's what this video is really going to focus on. So a queue is a lot like leaving a message, like leaving a voicemail or an email or something like that, where a future is actually saying, hey, we're going to synchronize the program execution. And there's a lot of science that happens in the background, but really they're two fundamentally different things. You can almost think of a queue like, well, in Mailbox and you're going to leave a message where a future is going to just say, hey, we're going to synchronize the execution. Let's dive in and take a look. To begin, we're going to kind of combine two sections we usually do different all into one. We're going to do the main and the imports. And we're just going to just flesh these out because they're so simple and we've covered them before. There's no point in separating them out into separate sections. So I'm going to do the old copy and paste. We're going to have a whole ton of imports. We have covered all of these. We're going to be doing logging, threading, threading. We're going to use the thread. I have that separate because I don't want to do threading.thread. I just want to be able to say thread, time, random. In current futures, we're going to import the thread pool executor. You of course need Python 3.2 or higher. And we have from queue, we're going to import queue. Now, our main function is, well, pretty simple, actually. This is kind of why I wanted to do it right now, just to get it out of the way. And we're going to go ahead and say main. Now, inside of our main, this is where we're going to do a bit of configuration. So I'm going to do the old copy and paste because we've already covered logging. We're going to do logging, basic config, and then we're going to have our level, time, milliseconds, with a message, and then our format. We're also going to have the log level of debug. So pretty much that's it for our boilerplate code. We're going to actually start diving in and fleshing out the rest of this application. OK, now is when we slow way down and you get to enjoy the soothing sounds of my voice while I try to type horribly because lately I just haven't been able to type well. I don't know why. All right, so we're going to talk about the queue first. So think of a queue as passing a message back and forth. We're going to make two fun things. We're going to say def. Let's call this queue you. Ah, queue, you, you, you, you, dude. Why say that five times real fast? I'm just going to pass on that. Probably choose a better function name. And let me scroll down and get some screen real estate here. And then we're going to say. Yeah, test. And we want to test the queue. And I'm just going to do pass on both just initially so we can start filling this in. We're going to say name and we want a queue. So really what we're going to do here is we're going to call a thread in this function. And it's going to actually call this function on the thread. Little confusing why we have these split up. But basically this creates the thread. This is what runs on the thread. So let's go ahead and let's fill this guy in first because it's going to be our code that's running on the thread. So I'm going to say thread equals and we want threading dot current and we want the name. From there we can say logging dot info and we've already set up logging in our main. So we don't have to worry about setting any of that up. And I'm going to say starting and we just want to know the red name from there a little bit of copy and paste action, save just a millisecond of typing this out. We can know that we have finished. Now is where we do our actual work. What I want to do here is I want to say time, sleep, we're just going to simulate like we're doing some sort of long activity, they random, Rand rage. And if none of this makes any sense, you need to go back and watch the previous videos because we've covered all this ad nauseum to the point. There's really no sense of covering it again, or this will be a much longer video. So now that we have all this, we've simulated that we're doing some sort of long operation on a thread because one to five seconds in computer time is just an eternity. What we're going to do now is put something into a queue. So I'm going to say correct, this is just going to be a value, hello. And then name and there's a bunch of different ways you can do this in Python. Just use whatever works for you. Or random number is, and this is basically all we're doing is just creating some kind of random number generation, we're going to make a string representation of a random Rand range. I like that term Rand range sounds like something out of like the shining that movie was scared me when I was a kid anyways. So Rand range, Rand rage. Now that we've got this big long string, we want to return this, but we're not going to do a return. We're going to put it in a queue. So we're going to say queue you because that's our queue object that we're going to pass onto this function. And we're going to say put. And this may cause subtle issues. I actually don't use queue very often. This is kind of like the older way of doing it. But if you're working in multi threaded applications, you'll have to make sure you lock and unlock if you really need to. But because we only really have one thread that's going to be doing this, I'm not going to really worry about it too much. Realistically though, you should lock that up and make sure you're not going to cause any sort of issues. All right, now that we've got all that, let's show you how that we can get the value from the thread. So we're going to say queue you equal. And well, boy, like I said, I just cannot type queue you equal. And we want our queue, we're going to create a new instance of a queue equal thread. Now in our thread, we want a target. And this is going to be that test queue function right up here. So we're just going to grab him. And then we're going to say args. I like that args always cracks me up when I say that because when I was in an office setting, people used to look at me funny when they just hear me down the hall go arg, I'm a pirate. But anyways, so now we have this, we're going to say t dot start. So we're just going to start that thread off. Then we're going to do a little bit of logging. We're just going to basically say, you know what, do something on the main thread. We're just going to go about our normal lives. And then when we're ready, we're going to say, you know what, we want to join that thread to the main thread because we want to get the information back. And this is where if you're in a truly multi-threaded environment, you need to lock, acquire, and then release. But for demonstration purposes, we're just going to ignore that. We're going to say get. And I did read somewhere, I'm not an expert, but I did read somewhere that it does it automatically in queue, but don't trust me on that. Again, I think there's a better way. And we're going to show that when we talk about futures. So logging.info, f dot, we want returned. And we just want to see what value we got back. Let's just grab this function, go down here. And we're going to call the cued function. Now, I'm just going to say it before I run this. I do not like working with queue. I just don't. I don't like the way you have to put and get. You've got to kind of track what you're doing. And then what do you do if you have multiple things? And then it gets into this whole thing where you're deep diving into the documentation. And it just, it sucks. And I have misspelled something. Oh, actually, no. There we go. There we go. So do something on the main thread. And then after a period of time, blah, returned. Hello, Brian, your random number is 43. That would have been super cool if that was 42. If you've ever read like Hitchhiker's Guide to the Galaxy, the answer is always 42. But anyways, we got 43. So that is a very simple way of working with threads and getting information you would put to a queue and then get from the queue. I personally don't like this. I think there's a better way and it's called futures, which we're going to cover right now. OK, futures. I love the working with futures. It's just like, have you ever just made a complete mess of your house and you look at it and go, you know what, this is a problem for future me. That's exactly what a future is. You can just do something and then worry about it when you actually need to worry about it. It's so much cleaner than working with a queue. But we're going to grab this guy right here, do the old copy paste. And we're going to call this test future. Going to do a little bit of surgery on this. So bear with me here. So we don't need this queue because we're not passing a queue object back and forth. And that means we don't need this right here. So we can just say return like we would normally return. This is why I like futures, because you don't have to like super depend on some other class. And then everything's just going to work the way you'd expect it to. You could call this like a normal function that would return a value. So now what we're going to do is actually work on a pool. And this is why I love futures. So we're going to say deaf pooled and like Deadpool. Anybody watch that movie Deadpool? I like all of them. All right, so workers equal 20. So we're going to have 20 threads. We're going to do 20 different times. We're going to get 20 different return values. This is insane. Comparing this to a queue. This is way, way better already. And we haven't even started. So we're going to say with. And you guys did thread pull executor. And we want the max workers equals workers. And then as EX and then for X in range, not random range. Thank you, keyboard workers. Maybe I need a new keyboard. It's December 2020, possibly one of the worst years ever. But hopefully maybe Santa Claus will bring me a keyboard this year. So we're going to say value equal. Random. Range. Why is it working? Random range. Random range. There we go. Boy, I'm just making all kinds of mistakes in this video. So we're going to get just a random number. Now we're going to call the executor submit. So let's go ahead and say future. Equals and we could have called that like F or something like that. EX.submit and we want to send this to our callable, which in this case is our test future function. And we want to say the name name. And because we've got 20 of these, we want to know which one we're doing here. So we're going to make a string representation of X. So there'll be Brian zero through 19 because we're doing the X in range workers, workers is 20. All right. Now what we're going to do is we're going to build up this list of return values. Here's the catch 22. Because we're working with threads, those values don't actually exist. This is why we need a future. We're saying that value will exist in the future, but it doesn't actually exist right now. When you think of futures, think it's like a placeholder for something we're going to work with. So we're going to say ret append, and we're going to append. That future. So basically what we're saying is Python, we're going to work with a value. We don't have the value yet, but this is my way of saying we're going to do something. All right, lots of stuff to talk about here. Let's grab this and just paste that in there. And from here, now what we're going to do is we're going to, in a sense, join all those threads back to our main thread in order with the results. And this is actually way simpler than it sounds. We're just going to say for our in our list of return values, logging dot info. And let's go ahead and say returned. That would been super cool if I had done that right the first time. Again, let's see if we can go for three here. There we go. Returned. And now we want the result. So really what happens under the hood here is you're going to say, we want all these futures put the futures in the list. And then later on after you've done something in your main thread, then you're going to say, okay, Python, all of those futures, we now want to work with those and we want to get the result under the hood. There's a lot that happens. But basically this is Python's way of going back to that thread saying, hey, give me what you have. If you're not done, I'm going to wait on you until you are done. And this is essentially doing the same thing as calling join. All right. So from here, we can just grab this function name. Let's comment him out and let's do it the future way, the way of the future. I don't know. I feel like I need like some big 1990s logo on the screen or something. Let's clear this out real quick. And we're going to have a lot of stuff. So let's just see here. All right, so you see all our threads are kicking off and they're now running in the background. And then in order, we have Brian zero through Brian 19. And then each one has a random number assigned to it. This is extremely cool. I love this. So when we're talking about futures and thread pools and things like that, for most other languages, this is tens of hours of conversations. I mean, we're sitting here talking for days about this, just so you understand the technology and then how to work with it. But with Python, you can have this conversation in minutes. I mean, literally not even an hour. You can learn how to work with a thread pool and learn what futures are and how to work with them. Wow, this is powerful stuff. So the main takeaway here is there are multiple ways to do it. And there's even more ways than what this video is covered. But a queue, you can basically act like a mailbox where you can put messages and get messages. But if you do this, you should lock and acquire and, you know, unlock, release, blah, blah, blah. Or you're going to end up with some multi-threaded issues. I really haven't taken that into consideration in this video just for the sake of time and complexity. Honestly, I believe the best way in my humble opinion is to work with the thread pool executor and work with futures because it handles all of that complexity in the background for you. You don't have to worry about it. All you have to do is collect a list of future values that you want to work with in the future. Then after you've done watching Netflix or video gaming or whatever you're doing, you can come back and say, hey, Python, now I want to get the result of each one of those futures. Very cool stuff. I hope you enjoyed this video. You can find the source code out on github.com. If you need additional help, myself and thousands of other developers are hanging out in the Voidrealms Facebook group. This is a large group with lots of developers and we talk about everything technology related, not just the technology that you just watched. And if you want official training, I do develop courses out on udemy.com. This is official classroom style training. If you go out there and the course you're looking for is just simply not there, drop me a note. I'm either working on it or I will actually develop it. I will put a link down below for all three of those. And as always, help me help you smash that like and subscribe button. The more popular these videos become, the more I'll create and publish out on YouTube. Thank you for watching.