Search code examples
pythonhttplib

Why can't I view updates to a label while making an HTTP request in Python


I have this code :

def on_btn_login_clicked(self, widget):
    email = self.log_email.get_text()
    passw = self.log_pass.get_text()
    self.lbl_status.set_text("Connecting ...")
    params = urllib.urlencode({'@log_email': email, '@log_pass': passw, '@action': 'login', '@module': 'user'})
    headers = {"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"}
    conn = httplib.HTTPConnection("website.com")
    self.lbl_status.set_text("Logging in ...")
    conn.request("POST", "/ajax.php", params, headers)
    response = conn.getresponse()
    print response.status
    self.lbl_status.set_text("")
    data = response.read()      
    print data
    conn.close()

The self.lbl_status doesn't change till the request is finished, so it displays nothing due to the last set_text function.

Why is this happening, and how to avoid/fix that?


Solution

  • Below is a working example of a simple downloader for illustration purposes only. You need to use multi-threading if you want your GUI to be responsive and not freeze while you do some long running or blocking operation. I put this example together based on this stack overflow question and this excellent article Using threads in PyGTK. The default url an Ubuntu iso will take a while to download and should provide a good demonstration . You can enter any url you want when prompted it will download and save the file in the current directory.

    from threading import Thread
    import time
    import gtk, gobject, urllib
    
    URL = 'http://releases.ubuntu.com//precise/ubuntu-12.04.1-desktop-i386.iso'
    
    def download(url):
        filename = url.split('/')[-1]
        out = open(filename, 'wb')
        gobject.idle_add(label.set_text, "connecting...")
        f = urllib.urlopen(url)
        buffer = f.read(1024)
        counter = 0
        while buffer:
            counter += len(buffer)
            out.write(buffer)
            msg = "downloaded {0:,} bytes".format(counter)
            gobject.idle_add(label.set_text, msg)
            buffer = f.read(1024)
        out.close()
        gobject.idle_add(label.set_text, "download complete")
    
    def clicked(button):
        url = entry.get_text()
        Thread(target=download, args=(url,)).start()
    
    
    gtk.gdk.threads_init()
    win = gtk.Window()
    win.set_default_size(400, 100)
    entry = gtk.Entry()
    entry.set_text(URL)
    label = gtk.Label("Press the button")
    button = gtk.Button(label="Download")
    button.connect('clicked', clicked)
    
    box = gtk.VBox()
    box.pack_start(entry)
    box.pack_start(label)
    box.pack_start(button)
    win.add(box)
    
    win.show_all()
    
    gtk.main()