A Guide to Threaded GUI clients in Python

DON'T post new tutorials here! Please use the "Pending Submissions" board so the staff can review them first.
Post Reply
User avatar
maboroshi
Dr. Mab
Dr. Mab
Posts: 1624
Joined: 28 Aug 2005, 16:00
18

A Guide to Threaded GUI clients in Python

Post by maboroshi »

Hello everyone here is a simple guide to threading and Tkinter for use with sockets and or high level network functions

In this example I take a part my Simple Sniff tool and build it using threads. I will explain the key concepts and show code that is needed for a threaded client using Python and Tkinter


We start by bringing in our import statements

Code: Select all

import time, random
from Tkinter   import *
from threading import *
from scapy import *
import tkFileDialog
Note the threading module, in that it is used instead of thread. The threading module is basically a higher lvl interface to thread

we then start to build our gui

Code: Select all


class ThreadedClient:
    def __init__(self, master=None):
        self.ok = 1
        
        self.master = master
        
	self.thread1= Thread(target=self.sniffit)       

        self.frame = frame = Frame(master)

        self.labelfilter = Label(frame, text="Filter")
        self.labelfilter.pack(side=LEFT)

        self.entryfilter = Entry(frame)
        self.entryfilter.pack(side=LEFT, fill=X, expand=True)


        self.labeli = Label(frame, text="Iface")
        self.labeli.pack(side=LEFT)

        self.entryiface = Entry(frame)
        self.entryiface.pack(side=LEFT, fill=X, expand=True)
        self.entryiface.insert(END, "eth0")

        self.start = Button(frame, text="Sniff It", command=self.run)
        self.start.pack(side=LEFT)


        self.save = Button(frame, text="Save It", command=self.windowit)
        self.save.pack(side=LEFT)

        self.btn = Button(frame, text='Close', command=self.shutdown)
        self.btn.pack(side=LEFT)
        frame.pack(fill=X)


        self.frame2 = frame2 = Frame(master)
        self.scrollbar = Scrollbar(frame2)
        self.scrollbar.pack(side=RIGHT, fill=Y)

        self.textbox = Text(frame2)
        self.textbox.pack(side=LEFT, fill=BOTH, expand=True)
        self.textbox.config(yscrollcommand=self.scrollbar.set)
        self.scrollbar.config(command=self.textbox.yview)
        self.frame2.pack(fill=BOTH, expand=True)
      
thats our entire gui code for the simple sniff client

take special note to

Code: Select all

self.thread1= Thread(target=self.sniffit) 
this initializes the function that needs to be threaded (so to speak)

also take note to

Code: Select all


 self.start = Button(frame, text="Sniff It", command=self.run)
 self.start.pack(side=LEFT)

the run function (which can be named anything you like) basically will start the threaded process defined (or our "sniffit" function) basically just starts the thread

this is some extra code we have just for gui functionality not necessary for our client but fun

Code: Select all

    def saveit(self):
        try:
            self.output1 = self.mysniff
            self.filename = self.entry2.get()
            wrpcap(self.filename, self.output1)
            self.entrystate.delete(0, END)
            self.entrystate.insert(END, "Data Saved")
        except:
            self.entrystate.delete(0, END)
            self.entrystate.insert(END, "Failed Saving Data")


    def windowit():
        self.top = top = Toplevel(root)
        top.title("Save Data")
        top.wm_resizable(0, 0)
        self.frame = frame = Frame(top)
        global entry2
        self.entry2 = Entry(frame)
        self.entry2.pack(side=LEFT)
        self.entry2.insert(END, "C:\\pcapfile.cap")
        self.savebutton = Button(frame, text="Save Data", command=self.saveit)
        self.savebutton.pack(side=LEFT)
        global entrystate
        self.entrystate = Entry(frame)
        self.entrystate.pack(side=LEFT)
        frame.pack()
next the run function


Code: Select all

    def run(self):
        self.thread1.start()
and our main program function

Code: Select all

    def sniffit(self):
        self.countit = 1
        self.filterit = str(self.entryfilter.get())
        self.setiface = str(self.entryiface.get())
            
        while self.ok:
            global mysniff
            self.mysniff = sniff(iface=self.setiface, count=self.countit, filter=self.filterit)
            self.a = "\n".join(map(lambda x:x.summary(), self.mysniff))
            self.textbox.insert(END, self.a)
            root.update()
time.sleep(0.1)

Now our function to kill the app

Code: Select all



    def shutdown(self):
        self.ok =0
        self.master.after(100, self.master.quit)

And finally to initialize our code and start the threaded client gui

Code: Select all


root = Tk()
root.minsize(300, 150)
root.option_readfile("optionDB")
root.wm_iconbitmap("shinobi.ico")
root.wm_resizable(0, 0)
root.title("Simple Sniff")
client = ThreadedClient(root)
root.mainloop()
Last edited by maboroshi on 17 Apr 2007, 16:40, edited 2 times in total.

User avatar
maboroshi
Dr. Mab
Dr. Mab
Posts: 1624
Joined: 28 Aug 2005, 16:00
18

Code

Post by maboroshi »

Here is the entire code now

Code: Select all

import time, random
from Tkinter   import *
from threading import *
from scapy import *
import tkFileDialog
conf.verb = 1

class ThreadedClient:
    def __init__(self, master=None):
        self.ok = 1
        
        self.master = master
        
	self.thread1= Thread(target=self.sniffit)       

        self.frame = frame = Frame(master)

        self.labelip = Label(frame, text="Filter")
        self.labelip.pack(side=LEFT)

        self.entryfilter = Entry(frame)
        self.entryfilter.pack(side=LEFT, fill=X, expand=True)


        self.labeli = Label(frame, text="Iface")
        self.labeli.pack(side=LEFT)

        self.entryiface = Entry(frame)
        self.entryiface.pack(side=LEFT, fill=X, expand=True)
        self.entryiface.insert(END, "eth0")

        self.start = Button(frame, text="Sniff It", command=self.run)
        self.start.pack(side=LEFT)


        self.save = Button(frame, text="Save It", command=self.windowit)
        self.save.pack(side=LEFT)

        self.btn = Button(frame, text='Close', command=self.shutdown)
        self.btn.pack(side=LEFT)
        frame.pack(fill=X)


        self.frame2 = frame2 = Frame(master)
        self.scrollbar = Scrollbar(frame2)
        self.scrollbar.pack(side=RIGHT, fill=Y)

        self.textbox = Text(frame2)
        self.textbox.pack(side=LEFT, fill=BOTH, expand=True)
        self.textbox.config(yscrollcommand=self.scrollbar.set)
        self.scrollbar.config(command=self.textbox.yview)
        self.frame2.pack(fill=BOTH, expand=True)
        
    def saveit(self):
        try:
            self.output1 = self.mysniff
            self.filename = self.entry2.get()
            wrpcap(self.filename, self.output1)
            self.entrystate.delete(0, END)
            self.entrystate.insert(END, "Data Saved")
        except:
            self.entrystate.delete(0, END)
            self.entrystate.insert(END, "Failed Saving Data")


    def windowit():
        self.top = top = Toplevel(root)
        top.title("Save Data")
        top.wm_resizable(0, 0)
        self.frame = frame = Frame(top)
        global entry2
        self.entry2 = Entry(frame)
        self.entry2.pack(side=LEFT)
        self.entry2.insert(END, "C:\\pcapfile.cap")
        self.savebutton = Button(frame, text="Save Data", command=self.saveit)
        self.savebutton.pack(side=LEFT)
        global entrystate
        self.entrystate = Entry(frame)
        self.entrystate.pack(side=LEFT)
        frame.pack()

    def run(self):
        self.thread1.start()

    def sniffit(self):
        self.countit = 1
        self.filterit = str(self.entryfilter.get())
        self.setiface = str(self.entryiface.get())
            
        while self.ok:
            global mysniff
            self.mysniff = sniff(iface=self.setiface, count=self.countit, filter=self.filterit)
            self.a = "\n".join(map(lambda x:x.summary(), self.mysniff))
            self.textbox.insert(END, self.a)
            root.update()
time.sleep(0.1)


    def shutdown(self):
        self.ok =0
        self.master.after(100, self.master.quit)
root = Tk()
root.minsize(300, 150)
root.option_readfile("optionDB")
root.wm_iconbitmap("shinobi.ico")
root.wm_resizable(0, 0)
root.title("Simple Sniff")
client = ThreadedClient(root)
root.mainloop()
Last edited by maboroshi on 17 Apr 2007, 16:40, edited 2 times in total.

User avatar
maboroshi
Dr. Mab
Dr. Mab
Posts: 1624
Joined: 28 Aug 2005, 16:00
18

REgards

Post by maboroshi »

Hope this helps someone in learning about threads and gui programming

cheers

Maboroshi

ebrizzlez
Kage
Kage
Posts: 732
Joined: 31 Mar 2007, 16:00
17
Location: Hidden in a Buffer Protection.
Contact:

Post by ebrizzlez »

Nice tutorial, well put. :wink: I really hated Python and thought it was a useless langauge, but you showed me otherwise. :roll: Thanks for the info, keep up the work. :wink:
[img]http://i81.photobucket.com/albums/j205/ebrizzlez/4lsint1.jpg[/img]

ulysse
Fame ! Where are the chicks?!
Fame ! Where are the chicks?!
Posts: 213
Joined: 15 Apr 2006, 16:00
18
Location: Quebec, CA
Contact:

Post by ulysse »

hah, python is actually the first language i tried to learn at age of 13... loong time ago.

Aight, only 2 years, but hey at this age id never even consider of using python to create GUI pgm 8O

ebrizzlez
Kage
Kage
Posts: 732
Joined: 31 Mar 2007, 16:00
17
Location: Hidden in a Buffer Protection.
Contact:

Post by ebrizzlez »

lol. It was the first language I tried as well... when I was 13 as well. :wink: Which I still am! :roll: lol. And I just hated the fact that you couldnt go back and easily edit all of your code, instead, after every line you entered and hit entered key, the code would execute itself. Which is a tad bit annoying, and Python was (and probley always will be) not for me. I never realized how useful Python was , till I went on HBH and saw various articles about port scanners and sniffers in Python! 8O But, I never built an interest for Python, due to the fact that Python has code execution, so after you enter line by line, the code executes, e.g. if you put 1+1 , the next line will soonly output the answer 2! And, unlike C/C++, it doesnt have a main() function that varifys it as the beginning of the program. That concept in Python confuses me alot, so thats why I just program in C++. :wink: but good work.
[img]http://i81.photobucket.com/albums/j205/ebrizzlez/4lsint1.jpg[/img]

pseudo_opcode
cyber messiah
cyber messiah
Posts: 1201
Joined: 30 Apr 2006, 16:00
17
Location: 127.0.0.1

Post by pseudo_opcode »

lol i dont know python but still i like this thread.. :?

ebrizzlez
Kage
Kage
Posts: 732
Joined: 31 Mar 2007, 16:00
17
Location: Hidden in a Buffer Protection.
Contact:

Post by ebrizzlez »

Python is a mix of commands founded in C/C++, such as the print or import functions are closely related to C/C++'s printf() function and the #include command as well. :wink: It's pretty basic, and a bit easier then C/C++ , but I find it can get real annoying and repetative. :roll:
[img]http://i81.photobucket.com/albums/j205/ebrizzlez/4lsint1.jpg[/img]

User avatar
maboroshi
Dr. Mab
Dr. Mab
Posts: 1624
Joined: 28 Aug 2005, 16:00
18

Judging from your posts

Post by maboroshi »

Judging from your posts I take it you do not know much about Python.
What is Python?

Python is an interpreted, interactive, object-oriented programming language. It is often compared to Tcl, Perl, Scheme or Java.

Python combines remarkable power with very clear syntax. It has modules, classes, exceptions, very high level dynamic data types, and dynamic typing. There are interfaces to many system calls and libraries, as well as to various windowing systems (X11, Motif, Tk, Mac, MFC, wxWidgets). New built-in modules are easily written in C or C++. Python is also usable as an extension language for applications that need a programmable interface.

The Python implementation is portable: it runs on many brands of UNIX, on Windows, OS/2, Mac, Amiga, and many other platforms. If your favorite system isn't listed here, it may still be supported, if there's a C compiler for it.
what python can do

Python is a high-level general-purpose programming language that can be applied to many different classes of problems.

The language comes with a large standard library that covers areas such as string processing (regular expressions, Unicode, calculating differences between files), Internet protocols (HTTP, FTP, SMTP, XML-RPC, POP, IMAP, CGI programming), software engineering (unit testing, logging, profiling, parsing Python code), and operating system interfaces (system calls, filesystems, TCP/IP sockets).

User avatar
Pong18
Cyber Mushroom
Cyber Mushroom
Posts: 357
Joined: 20 May 2009, 16:00
14
Location: Manila, Philippines
Contact:

Post by Pong18 »

python is the best language for me! i only learned it recently and i am in love with it!

just to share, here is my first program in python it's just a simple console calculator i made 2 years ago when i first learned it:

Code: Select all

import math

loop = 1
choice = 0

def menu():
    print "Welcome to Pongculator Console!"
    print "Select a function below"
    print " "
    print "1. Addition"
    print "2. Subtraction"
    print "3. Multiplication"
    print "4. Division"
    print "5. Square a value"
    print "6. Cube a value"
    print "7. Raise a value to"
    print "8. Find Square Root"
    print "9. Exit Pongculator"
    print " "
    try:
        return input("Enter the number of your choice here: ")
    except NameError:
        print "You have selected an item that is not on the list!"
        raw_input("Press Any Key to Continue...")
        menu()
def addme(x,y):    
    tot = x + y
    print x, " + ", y, " = ", tot    
def subme(y,x):    
    tot = x - y
    print x, " - ", y, " = ", tot
def mulme(x,y):
    tot = x * y
    print x, " x ", y, " = ", tot    
def divme(x,y):
    try:
        tot = x / y
        print x, " ÷ ", y, " = ", tot
    except ZeroDivisionError:
        print "Error! You cannot divide any value by Zero!"
        raw_input("Press Any Key to Continue...")
def sqrme(x):
    tot = x * x
    print x, " squared, is ", tot
def cubme(x):   
    tot = x ** x
    print x, " cubed, is ", tot
def powme(x,y):    
    tot = math.pow(x,y)
    print x, " raised to the power of ", y, " is ", tot
def sqtme(x):
    try:
        tot = math.sqrt(x)
        print "The square root of ", x, " is ", tot
    except ValueError:
        print "Error! No negative number can have a real square root!"
    
while loop == 1:
    choice = menu()
    if choice == 1:        
        try:
            print " "
            addme(input("Add this number: "),input("To this number: "))
            raw_input("Press Any Key to Continue...")
        except NameError:
            print "Error! You cannot perform addition on letters!"
            print "Please enter a valid number."
            raw_input("Press Any Key to Continue...")
    elif choice == 2:
        try:
            print " "
            subme(input("Subtract this number: "),input("from this number: "))
            raw_input("Press Any Key to Continue...")
        except NameError:
            print "Error! You cannot perform subtraction on letters!"
            print "Please enter a valid number."
            raw_input("Press Any Key to Continue...")
    elif choice == 3:
        try:
            print " "
            mulme(input("Multiply this number: "),input("By this number: "))
            raw_input("Press Any Key to Continue...")
        except NameError:
            print "Error! You cannot perform multiplication on letters!"
            print "Please enter a valid number."
            raw_input("Press Any Key to Continue...")
    elif choice == 4:
        try:
            print " "
            divme(input("Divide this number: "),input("By this number: "))
            raw_input("Press Any Key to Continue...")
        except NameError:
            print "Error! You cannot perform division on letters!"
            print "Please enter a valid number."
            raw_input("Press Any Key to Continue...")
    elif choice == 5:
        try:
            print " "
            sqrme(input("Square this number: "))
            raw_input("Press Any Key to Continue...")
        except NameError:
            print "Error! You cannot raise the value of letters!"
            print "Please enter a valid number."
            raw_input("Press Any Key to Continue...")
    elif choice == 6:
        try:
            print " "
            cubme(input("Cube this number: "))
            raw_input("Press Any Key to Continue...")
        except NameError:
            print "Error! You cannot raise the value of letters!"
            print "Please enter a valid number."
            raw_input("Press Any Key to Continue...")
    elif choice == 7:
        try:
            print " "
            powme(input("Take this number: "),input("And raise it to the power of: "))
            raw_input("Press Any Key to Continue...")
        except NameError:
            print "Error! You cannot raise the value of letters!"
            print "Please enter a valid number."
            raw_input("Press Any Key to Continue...")
    elif choice == 8:
        try:
            print " "
            sqtme(input("Find the square root of this number: "))
            raw_input("Press Any Key to Continue...")
        except NameError:
            print "Error! You cannot raise the value of letters!"
            print "Please enter a valid number."
            raw_input("Press Any Key to Continue...")
    else:
        raw_input("Press Any Key to Exit...")
        break
print "Thank you for using Pongculator!"     
Image

User avatar
lilrofl
Siliconoclast
Siliconoclast
Posts: 1363
Joined: 28 Jan 2009, 17:00
15
Location: California, USA
Contact:

Post by lilrofl »

python is pretty powerful, and while can use c-types, it isn't based in c at all I don't believe.

Sounds like you were learning python in the interpreter, where lines of code are executed while you write them... IDLE and SPE are examples of environments where that isn't the case.

I like SPE :)

python can be used to make all kinds of neat stuff, good examples would be scapy, pydbg or sully... all fun, all python ;)

oh yeah, thanks Mabs!! It's good to see you around, I was starting to wonder if the aliens picked you up for an anal probe....
knuffeltjes voor mijn knuffel
[img]http://i911.photobucket.com/albums/ac320/stuphsack/Sig.jpg[/img]

User avatar
leetnigga
Fame ! Where are the chicks?!
Fame ! Where are the chicks?!
Posts: 447
Joined: 28 Jul 2009, 16:00
14

Post by leetnigga »

lilrofl wrote:Sounds like you were learning python in the interpreter, where lines of code are executed while you write them...
Indeed. The Python REPL I think is actually one of Python's greatest strengths, but you can use Python just like other languages by writing the code in a file and executing that with the Python interpreter.
lilrofl wrote:python is pretty powerful, and while can use c-types, it isn't based in c at all I don't believe.
The CPython implementation of Python (the one from www.python.org) is written in C. It's also possible to extend Python with C or C++, so you could write C or C++ code and use it in your Python program! It's pretty awesome when you realize all programming languages are just written in eachother.

Nice work, Pong18.

Code: Select all

def divme(x,y):
    try:
        tot = x / y
        print x, " ÷ ", y, " = ", tot
    except ZeroDivisionError:
        print "Error! You cannot divide any value by Zero!"
        raw_input("Press Any Key to Continue...") 
Yes you can, it results in infinity :P

Instead of using break you could set loop to 0, which would be cleaner. I'd also rename the variable to "running" or something and make it a boolean so you can say:

Code: Select all

while running:
Which is pretty.

User avatar
leetnigga
Fame ! Where are the chicks?!
Fame ! Where are the chicks?!
Posts: 447
Joined: 28 Jul 2009, 16:00
14

Post by leetnigga »

Here's a funny alternative implementation of Pong's calculator that I cooked up:

Code: Select all

import math
from functools import reduce

operations = {'Addition' : [['Add this number', 'To this number'], '%d + %d = %d', lambda x, y: x + y],
              'Subtraction' : [['Take this number', 'And subtract this number'], '%d - %d = %d', lambda x, y: x - y],
              'Square root' : [['Find the square root of this number'], 'The square root of %d is %d', lambda x: math.sqrt(x)]}

def do_operation(op_index):
    operation = tuple(operations.keys())[op_index]
    questions = operations[operation][0]
    answer_format = operations[operation][1]
    op = operations[operation][2]
    inputs = []
    for question in questions:
        inputs.append(int(input(question+': ')))
    try:
        answer = op(*inputs)
        return answer_format % (tuple(inputs) + tuple([answer]))
    except Exception as e:
        word = 'input' if len(inputs) == 1 else 'inputs'
        return 'Cannot perform the operation \'%s\' on %s %s: %s' % (operation, word, reduce(lambda x,y: x+y, map(str,inputs)),str(e))

def main():
    running = True
    while running:
        i = 1
        for operation in operations:
            print('%d. %s' % (i, operation))
            i = i + 1
        print('%d. %s' % (i, 'Exit calculator'))
        operation_num = int(input('Enter the operation of your choice: '))
        if operation_num > i:
            print('You have selected an item that is not on the list!')
            pass
        if operation_num == i:
            running = False
            continue
        print(do_operation(operation_num-1))
        input('Press Enter to continue: ')
        print()

if __name__ == '__main__':
    main()

User avatar
Pong18
Cyber Mushroom
Cyber Mushroom
Posts: 357
Joined: 20 May 2009, 16:00
14
Location: Manila, Philippines
Contact:

Post by Pong18 »

leetnigga wrote:Here's a funny alternative implementation of Pong's calculator that I cooked up:

Code: Select all

import math
from functools import reduce

operations = {'Addition' : [['Add this number', 'To this number'], '%d + %d = %d', lambda x, y: x + y],
              'Subtraction' : [['Take this number', 'And subtract this number'], '%d - %d = %d', lambda x, y: x - y],
              'Square root' : [['Find the square root of this number'], 'The square root of %d is %d', lambda x: math.sqrt(x)]}

def do_operation(op_index):
    operation = tuple(operations.keys())[op_index]
    questions = operations[operation][0]
    answer_format = operations[operation][1]
    op = operations[operation][2]
    inputs = []
    for question in questions:
        inputs.append(int(input(question+': ')))
    try:
        answer = op(*inputs)
        return answer_format % (tuple(inputs) + tuple([answer]))
    except Exception as e:
        word = 'input' if len(inputs) == 1 else 'inputs'
        return 'Cannot perform the operation \'%s\' on %s %s: %s' % (operation, word, reduce(lambda x,y: x+y, map(str,inputs)),str(e))

def main():
    running = True
    while running:
        i = 1
        for operation in operations:
            print('%d. %s' % (i, operation))
            i = i + 1
        print('%d. %s' % (i, 'Exit calculator'))
        operation_num = int(input('Enter the operation of your choice: '))
        if operation_num > i:
            print('You have selected an item that is not on the list!')
            pass
        if operation_num == i:
            running = False
            continue
        print(do_operation(operation_num-1))
        input('Press Enter to continue: ')
        print()

if __name__ == '__main__':
    main()
hehe! nice 1 leet! its like a RARd version of my first calc! hehe! ^_^
Image

Post Reply