How it works...

In this recipe, we extended the Thread class to implement the logic that must run in a separate thread using a more object-oriented approach. This is done by overriding its run() method, which will be responsible for performing the HTTP request to the local server:

class AsyncAction(threading.Thread):
def run(self):
# ...

There are lots of HTTP client libraries, but here we will simply use the urllib.request module from the standard library. This module contains the urlopen() function, which can take a URL string and return an HTTP response that can work as a context manager—that is, it can be safely read and closed using the with statement.

The server returns a JSON document like the following one (you can check it by opening the http://localhost:8080 URL in your browser):

{"random": 0.0915826359180778}

To decode the string to a object, we pass the response contents to the loads() function from the json module. Thanks to this, we can access the random value like using a dictionary, and store it in the result attribute, which is initialized to None to prevent the main thread from reading a field that is not set in case an error occurs:

def run(self):
self.result = None
url = "http://localhost:8080"
with urllib.request.urlopen(url) as f:
obj = json.loads(f.read().decode("utf-8"))
self.result = obj["random"]

Then, the GUI periodically polls the thread status, as we saw in the preceding recipe:

    def check_thread(self, thread):
if thread.is_alive():
self.after(100, lambda: self.check_thread(thread))
else:
text = "Random value: {}".format(thread.result)
self.label.config(text=text)
self.button.config(state=tk.NORMAL)

Here, the main difference is that once the thread is not alive, we can retrieve the value of the result attribute because it has been set before finishing its execution.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset