Python action freezes the program - python

I have this little program I wrote, In it there is a class of methods, and a class that build the window (only one).
from Tkinter import *
from tkMessageBox import *
import socket
import platform ,sys
import subprocess
from multiprocessing.pool import ThreadPool
import Queue
import threading
class Methods(object):
def __init__(self):
#TODO : implement
pass
def getHostName(self):
try:
return socket.gethostname()
except:
return "ERROR :Could'nt get Hostname"
def getOperatingSystem(self):
try:
return platform.system() + " " + platform.release() + " " + platform.version() + " " + sys.getwindowsversion()[4]
except:
return "ERROR :Could'nt get Operating System"
def getHotFixes(self,queue):
try:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
myProcess = subprocess.Popen(
"wmic qfe get HotFixID, InstalledOn",
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
startupinfo = startupinfo)
out, error = myProcess.communicate()
full_list = out.splitlines()
result = ""
for item in full_list:
if item != "" and item != " ":
result += "%s \n" % item
out_number = len(result.splitlines()) - 1
a = "There Are %s Microsoft HotFixes Updates \n\n%s" % (out_number , result)
queue.put(a)
except:
return "ERROR :Could'nt get HotFixes"
#VISUAL
#This class will have an instance of Methods and call every action by itself.
class MainWindow(object):
def __init__(self):
self.root = Tk()
self.root.title('SAAP')
self.root.geometry('610x440+100+100')
#self.root.resizable(0,0)
self.methods = Methods()
def openHostName():
disableAllButtons(self)
result = self.methods.getHostName()
print result
self.textLabelString.set("Host Name")
self.textBox.config(state=NORMAL)
self.textBox.delete("1.0",END)
self.textBox.insert(INSERT,result)
self.textBox.config(state=DISABLED)
enableAllButtons(self)
def openOperatingSystem():
disableAllButtons(self)
result = self.methods.getOperatingSystem()
print result
self.textLabelString.set("Operating System")
self.textBox.config(state=NORMAL)
self.textBox.delete("1.0",END)
self.textBox.insert(INSERT,result)
self.textBox.config(state=DISABLED)
enableAllButtons(self)
def openHotFixes():
queue = Queue.Queue()
thread_ = threading.Thread(
target = self.methods.getHotFixes,
name='Thread1',
args=[queue],
)
thread_.start()
thread_.join()
result = queue.get()
disableAllButtons(self)
self.textLabelString.set("Microsoft Hotfixes")
self.textBox.config(state=NORMAL)
self.textBox.delete("1.0",END)
self.textBox.insert(INSERT,result)
self.textBox.config(state=DISABLED)
enableAllButtons(self)
#items decleration
self.actionLabel = Label(self.root, text = 'Actions',bg='blue',fg='white')
self.button1 = Button(self.root, text = 'Host Name' , command=openHostName)
self.button2 = Button(self.root, text = 'Operating System' , command = openOperatingSystem)
self.button3 = Button(self.root, text = 'Microsoft HotFixes' , command = openHotFixes)
self.button4 = Button(self.root, text = 'N4')
self.button5 = Button(self.root, text = 'Fi5o')
self.button6 = Button(self.root, text = 'C6y')
self.button7 = Button(self.root, text = '7')
self.button8 = Button(self.root, text = '8y')
self.button9 = Button(self.root, text = 'R9s')
self.button10 = Button(self.root, text = '10t')
self.button11 = Button(self.root, text = 'I11s')
self.textLabelString = StringVar()
self.textLabel = Label(self.root,bg='black',fg='white',width=60,textvariable=self.textLabelString)
self.textLabelString.set("Output")
self.textBox = Text(self.root,width=52)
self.textBox.insert(INSERT,"Here's the output")
self.textBox.config(state=DISABLED)
self.scrollBar = Scrollbar(self.root)
self.scrollBar.config(command=self.textBox.yview)
self.textBox.config(yscrollcommand=self.scrollBar.set)
#items placing
self.actionLabel.grid(row=0,column=0,sticky=W+E+N+S,pady=5)
self.button1.grid(row=1,column=0,padx=5,pady=5,sticky=W+E)
self.button2.grid(row=2,column=0,padx=5,pady=5,sticky=W+E)
self.button3.grid(row=3,column=0,padx=5,pady=5,sticky=W+E)
self.button4.grid(row=4,column=0,padx=5,pady=5,sticky=W+E)
self.button5.grid(row=5,column=0,padx=5,pady=5,sticky=W+E)
self.button6.grid(row=6,column=0,padx=5,pady=5,sticky=W+E)
self.button7.grid(row=7,column=0,padx=5,pady=5,sticky=W+E)
self.button8.grid(row=8,column=0,padx=5,pady=5,sticky=W+E)
self.button9.grid(row=9,column=0,padx=5,pady=5,sticky=W+E)
self.button10.grid(row=10,column=0,padx=5,pady=5,sticky=W+E)
self.button11.grid(row=11,column=0,padx=5,pady=5,sticky=W+E)
self.textLabel.grid(row=0,column=1,padx=10,pady=5)
self.textBox.grid(row=1,column=1,rowspan=11,pady=5)
self.scrollBar.grid(row=1,column=2,rowspan=11,sticky=N+S)
def disableAllButtons(self):
self.button1['state'] = DISABLED
self.button2['state'] = DISABLED
self.button3['state'] = DISABLED
self.button4['state'] = DISABLED
self.button5['state'] = DISABLED
self.button6['state'] = DISABLED
self.button7['state'] = DISABLED
self.button8['state'] = DISABLED
self.button9['state'] = DISABLED
self.button10['state'] = DISABLED
self.button11['state'] = DISABLED
def enableAllButtons(self):
self.button1['state'] = NORMAL
self.button2['state'] = NORMAL
self.button3['state'] = NORMAL
self.button4['state'] = NORMAL
self.button5['state'] = NORMAL
self.button6['state'] = NORMAL
self.button7['state'] = NORMAL
self.button8['state'] = NORMAL
self.button9['state'] = NORMAL
self.button10['state'] = NORMAL
self.button11['state'] = NORMAL
def main():
mainw = MainWindow()
mainw.root.mainloop()
if __name__ == "__main__":
main()
Now , My problem is when I press a button it needs to do something and then the output should appear on screen.
BUT, and here comes the but --
when the action takes a bit, it freezes the program until the action is done.
I want to make the program treat maybe the action as a different thread so it won't freeze.
I tried some stuff but it did not worked for me unfortunately ...
Any Help ?
Appreciated!

It is ok to execute your actions in separate threads, however you need to implement a
mechanism for signaling to your main thread (where Tk's loop is running) when actions
are finished, and to get the result(s).
One approach is to have a proper Action class, creating thread objects ; you pass
the method to execute and its arguments, then you start the thread - beforehand,
you register a callback that will be called in your Tk loop when action is finished.
In order to pass results from the thread to the callback, a Queue can be used:
import functools
class Action(threading.Thread):
def __init__(self, method, *args):
threading.Thread.__init__(self)
self.daemon = True
self.method=method
self.args=args
self.queue=Queue.Queue()
def run(self):
self.queue.put(self.method(*self.args))
def register_callback(self, tkroot, callback):
# to be called by Tk's main thread,
# will execute the callback in the Tk main loop
try:
result = self.queue.get_nowait()
except:
# set a timer, to check again for results within 100 milliseconds
tkroot.after(100, functools.partial(self.register_callback,
tkroot, callback))
else:
return callback(result)
EDIT: modification of the original example to show how to apply this to the getHotFixes
method
As an example, here is how to change getHotFixes accordingly:
class Methods(object):
...
def getHotFixes(self):
try:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
myProcess = subprocess.Popen("wmic qfe get HotFixID, InstalledOn",
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
startupinfo = startupinfo)
out, error = myProcess.communicate()
full_list = out.splitlines()
result = ""
for item in full_list:
if item != "" and item != " ":
result += "%s \n" % item
out_number = len(result.splitlines()) - 1
return "There Are %s Microsoft HotFixes Updates \n\n%s" % (out_number , result)
except:
return "ERROR :Could'nt get HotFixes"
Finally, in MainWindow you just need to call the getHotFixes method, register
a callback to do something useful with the result when it's finished using
register_callback and call start() to start the Action thread:
class MainWindow(object):
def __init__(self):
self.root = Tk()
...
def openHotFixes():
disableAllButtons(self)
action = Action(self.methods.getHotFixes)
action.register_callback(self.root, openHotFixesDone)
action.start()
def openHotFixesDone(result):
self.textLabelString.set("Microsoft Hotfixes")
self.textBox.config(state=NORMAL)
self.textBox.delete("1.0",END)
self.textBox.insert(INSERT,result)
self.textBox.config(state=DISABLED)
enableAllButtons(self)
Hope this helps.

Related

How to change the background color of the box in Tkinter with an action

import platform
import subprocess
from tkinter import *
###IPs to use
iptoscan = {
'test': '8.8.8.8',
'test 2' : '7.7.7.7',
'test 3' : '1.1.1.1'
}
###Ping function
def ping(ipAddr: object, timeout: object = 100) -> object:
if platform.system().lower() == 'windows':
numFlag = '-n'
else:
numFlag = '-c'
global completedPing
completedPing = subprocess.run(['ping', numFlag, '1', '-w', str(timeout), ipAddr],
stdout=subprocess.PIPE, # Capture standard out
stderr=subprocess.STDOUT) # Capture standard error
if completedPing.returncode == 0: # I need this if command to send the IP address and a True command
pingstatus = "Network Active " # Active ping response
else: # I need this to send the IP plus a False command
pingstatus = "Network Error " # No ping response
print(pingstatus + ipAddr)
return (completedPing.returncode == 0) and (b'TTL=' in completedPing.stdout)
###Function to ping from dictionary
def multiping():
for ips in iptoscan:
ping(iptoscan[ips])
if completedPing.returncode == 0:
return True
else:
print("notworking")
My question
Instead of using a "ButtonPress" I want to have the boxes change with the result of the ping, true turns green false stays red. So basically as soon as the code runs I want it to ping from the dictionary and if the results are true I want it to change the color of each box.
class OneSquare():
def __init__(self, can, start_x, start_y, size):
self.can=can
self.id = self.can.create_rectangle((start_x, start_y,
start_x+size, start_y+size), fill="red")
self.can.tag_bind(self.id, "<ButtonPress-1>", self.set_color)
self.color_change=True
def set_color(self, event=None):
self.color_change = not self.color_change
color="red"
if not self.color_change:
color="green"
self.can.itemconfigure(self.id, fill=color)
root = Tk()
canvas = Canvas(root)
canvas.grid(column=1, row=1, sticky=(N, S, E, W))
#Boxes to display the network status
IP1=OneSquare(canvas, 1, 1, 30)
IP2=OneSquare(canvas, 1, 50, 30)
IP3=OneSquare(canvas, 1, 100, 30)
#Exit button
Button(root, text="Exit", bg="orange",
command=root.quit).grid(row=2)
multiping()
root.mainloop()
This is a little tricky questions because ping requests called from OS may have delays in them when the destination device is unreachable. This will cause constant tkinter freezes and delays in your program as the loop goes. To avoid such scenarios simplest way is to use threads (which tkinter is not fond of).
You would need to have a separate thread that does these requests constantly and ends when tkinter does. Make sure you're not doing any calls from that thread to your widgets, as that will make unexpected errors and crashes occur.
Here is a simple example which you can apply to your code:
import subprocess, time
from tkinter import *
from threading import Thread
iptoscan = { # Your IP list
'test': '8.8.8.8',
'test 2' : '7.7.7.7',
'test 3' : '1.1.1.1'
}
def startPing():
while root:
for id in iptoscan:
process = subprocess.Popen(['ping', iptoscan[id], '-n', '1'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # This is just for windows OS (the system i'm testing on), -n 1 if for sending only one ping request
#labels[id][1] = process.stdout.read().split('\r\n')[2] # for python 2.x
labels[id][1] = str(process.stdout.read()).split('\\r\\n')[2]
time.sleep(1) # Delay between ping requests
def updateLabels():
for id in labels:
if 'time=' in labels[id][1]: # This could be our trigger for knowing if ping was successful
labels[id][0].configure(bg = 'green', text = 'IP: ' +iptoscan[id] + ', time: ' + labels[id][1].split('time=')[1].split(' ')[0] ) # I'm updating the names also as you can see
else:
labels[id][0].configure(bg = 'dark orange', text = 'IP: ' +iptoscan[id] + ' ' +labels[id][1] ) # If the requst fails, display the message
root.after(100, updateLabels) # Continue the loop
root = Tk()
root.geometry('300x120')
labels = {} # We'll store the label widget and ping response in this dictionary
for id in iptoscan:
label = Label(root, text = 'IP: ' + iptoscan[id] )
label.pack(side='bottom',pady=10)
labels[id] = [label, ''] # First element will be the widget and second one the response
Thread(target = startPing).start() # Starting the thread to perform ping requests
root.after(100, updateLabels) # Starting to loop the function that will update ping responses to our widgets
root.mainloop()
root = None

PyQt4 window disappears when back end runs and re-appears when finished

I am very new to PyQt4 and was learning how to integrate it with my Python code at the back-end. The way I did it, the front-end looks just fine and takes all the input I need. When the processing starts, that is when the back-end scripts run, the window disappears and reappears when all my back end scripts have finished. The window is supposed to show the status of the on-going process (at the back end).
Please help me with this.
A Button on Win2 makes it switch to Win4 and that is when Win4 disappears and reappears once all the back end processing is done.
Code snippet:
class Win2(QtGui.QMainWindow, w2):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.move(500,200)
self.window1 = None
self.window4 = None
self.window5 = None
self.window6 = None
self.pushButton_2.clicked.connect(self.showWin4)
self.pushButton_9.clicked.connect(self.showWin5)
self.pushButton_5.clicked.connect(self.showWin6)
self.pushButton_8.clicked.connect(self.openIP)
self.pushButton_7.clicked.connect(self.opencred)
self.pushButton_6.clicked.connect(self.showWin1)
def openIP(self):
self.filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
#print filename
self.label_7.setText(self.filename)
def from_alldevicesrun(self):
#print check_port.all_ips
with open(self.filename, "rb") as csvfile:
iprow = csv.reader(csvfile, delimiter='\n')
for [ip] in iprow:
#print ip
from_alldevices.ips.append(ip)
csvfile.close()
from_alldevices.main()
def opencred(self):
self.filename1 = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
#print filename1
self.label_9.setText(self.filename1)
def see_cred(self):
'''
import __builtin__
__builtin__.x = self.filename1
import check_credentials_both
'''
cmd = ['python', 'c.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def showWin4(self):
self.close()
if self.window4 is None:
self.window4 = Win4()
self.window4.show()
self.window4.set_status_7('Ongoing')
self.from_alldevicesrun()
self.window4.set_status_7('Done')
self.window4.set_status_13('Ongoing')
self.see_cred()
self.window4.set_status_13('Done')
self.window4.set_status_8('Ongoing')
self.window4.get_data_from_server()
self.window4.set_status_8('Done')
self.window4.set_status_9('Ongoing')
self.window4.SSH_into_nw()
self.window4.set_status_9('Done')
self.window4.set_status_10('Ongoing')
self.window4.extract_mac()
self.window4.extract_lldp()
self.window4.port_channel_change()
self.window4.final_algo()
self.window4.set_status_10('Done')
self.window4.showWin10()
def showWin5(self):
if self.window5 is None:
self.window5 = Win5(self)
self.window5.show()
def showWin6(self):
if self.window6 is None:
self.window6 = Win6(self)
self.window6.show()
def showWin1(self):
self.close()
if self.window1 is None:
self.window1 = Win1(self)
self.window1.show()
class Win4(QtGui.QDialog, w4):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
self.move(500,200)
self.window10 = None
self.pushButton.clicked.connect(self.show_graphandWin8)
self.pushButton_2.clicked.connect(self.showWin10)
self.window8 = None
def show_graphandWin8(self):
#self.close()
if self.window8 is None:
self.window8 = Win8(self)
self.window8.show()
cmd = ['python', 'dc.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def set_status_7(self,text):
self.label_7.setText(text)
def set_status_8(self,text):
self.label_8.setText(text)
def set_status_9(self,text):
self.label_9.setText(text)
def set_status_10(self,text):
self.label_10.setText(text)
def set_status_13(self,text):
self.label_13.setText(text)
def get_data_from_server(self):
get_data_from_servers.main()
def SSH_into_nw(self):
import SSH_and_telnet_nw
SSH_and_telnet_nw.main()
def extract_mac(self):
cmd = ['python', '123.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def extract_lldp(self):
cmd = ['python', 'qwe.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def port_channel_change(self):
import change_to_port_channel
change_to_port_channel.main()
def final_algo(self):
cmd = ['python', 'abc.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def showWin10(self):
if self.window10 is None:
self.window10 = Win10(self)
self.window10.show()
def main():
app = QtGui.QApplication(sys.argv)
form = Win2()
form.show()
sys.exit(app.exec_())
Thank you in advance.
You want to use hide() not close(). When you are calling self.close() you are making the QMainWindow stop and potentially be set for deletion. With hide() it will just make the Window invisible until you want to show() it again.
def showWin4(self):
self.hide() #This should be a hide not close
if self.window4 is None:
self.window4 = Win4()
self.window4.show()

Python socket client/server select problems

We are attempting to make our python messenger system more efficient. Currently both the client and the server use ridiculous amounts of the CPU while running and communicating. We suspect this is due to the receiving/connecting loop trying constantly to receive a message or user/password.
the message receiving loop follows:
def recvmsg():
global decrypted_text
while not shutdown:
response = s.recv(4096).decode('utf-8')
response = decrypt(response)
if response.startswith("dict_keys(['"):
formatted = response.replace("dict_keys(['", "")
formatted = formatted.replace("'])", "")
formatted = formatted.replace("'", "")
output_field.configure(state = "normal")
output_field.insert(END, "Connected users: " + formatted + "\n")
output_field.see(END)
output_field.configure(state = "disabled")
else:
output_field.configure(state = "normal")
output_field.insert(END, response + "\n")
output_field.see(END)
output_field.configure(state = "disabled")
we are attempting to utilize the select module to have the loops wait for incoming traffic instead of looping and failing into infinity.
we have looked here: http://ilab.cs.byu.edu/python/select/echoserver.html for help but we didn't get very far because we got this error: [WinError 10022] An invalid argument was supplied. we also looked in the python documentation here: https://docs.python.org/3/library/select.html?highlight=select#module-select
You may find this answer to be helpful in implementing your server. If you wish for a more complete server implementation, that can be provided as well. In developing the complex version of the server, a variety of features were developed including friend lists, private messaging, and individual communication channels.
Simple_Server.py
#! /usr/bin/env python3
import socket, select
def main():
a = [socket.socket(socket.AF_INET, socket.SOCK_STREAM)] # socket array
a[0].bind(('', 8989))
a[0].listen(5)
while True:
for b in select.select(a, [], [])[0]: # ready socket
if b is a[0]:
a.append(b.accept()[0])
else:
try:
c = b.recv(1 << 12) # sent message
except socket.error:
b.shutdown(socket.SHUT_RDWR)
b.close()
a.remove(b)
else:
for d in (d for d in a[1:] if d is not b): # message sink
d.sendall(c)
if __name__ == '__main__':
main()
MultichatClient.py
#! /usr/bin/env python3
from safetkinter import *
from tkinter.constants import *
import socket
import sys
class MultichatClient(Frame):
after_handle = None
def __init__(self, master, remote_host):
super().__init__(master)
self.message_area = ScrolledText(self, width=81, height=21,
wrap=WORD, state=DISABLED)
self.message_area.grid(sticky=NSEW, columnspan=2)
self.send_area = Entry(self)
self.send_area.bind('<Return>', self.keyPressed)
self.send_area.grid(sticky=EW)
b = Button(self, text='Send', command=self.mouseClicked)
b.grid(row=1, column=1)
self.send_area.focus_set()
try:
self.remote = socket.create_connection((remote_host, 8989))
except socket.gaierror:
print('Could not find host {}.'.format(remote_host))
except socket.error:
print('Could not connect to host {}.'.format(remote_host))
else:
self.remote.setblocking(False)
self.after_handle = self.after_idle(self.dataready)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
#classmethod
def main(cls, args):
root = Tk()
root.title('MultichatClient version 1.0')
m = cls(root, args[0])
m.grid(sticky=NSEW)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
return 1
def dataready(self):
try:
s = self.remote.recv(1 << 12).decode()
except socket.error:
pass
else:
self.message_area['state'] = NORMAL
self.message_area.insert(END, s)
self.message_area['state'] = DISABLED
self.message_area.see(END)
self.after_handle = self.after(100, self.dataready)
def destroy(self):
if self.after_handle:
self.after_cancel(self.after_handle)
super().destroy()
def mouseClicked(self, e=None):
self.remote.sendall(self.send_area.get().encode() + b'\r\n')
self.send_area.delete(0, END)
keyPressed = mouseClicked
if __name__ == '__main__':
sys.exit(MultichatClient.main(sys.argv[1:]))

Python GTK GUI struck

I'm using python gtk to upload file to S3 service by boto API , GUI struck when uploading a file and releases the GUI after completed process of upload, I'm using thread to show progress of upload in GUI but it struck. Can you some suggestion how to show progress of upload in GUI or any spinner until upload finish. I'm new to python can u suggest how to use thread for GUI also.
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
import boto
from boto.s3.connection import S3Connection
from boto.s3.key import Key
from boto.exception import S3ResponseError, S3CreateError
import threading
import random, time
gtk.threads_init()
class FractionSetter(threading.Thread):
"""This class sets the fraction of the progressbar"""
#Thread event, stops the thread if it is set.
stopthread = threading.Event()
def run(self):
"""Run method, this is the code that runs while thread is alive."""
#Importing the progressbar widget from the global scope
global progressbar
#While the stopthread event isn't setted, the thread keeps going on
while not self.stopthread.isSet() :
# Acquiring the gtk global mutex
gtk.threads_enter()
#Setting a random value for the fraction
progressbar.set_fraction(random.random())
# Releasing the gtk global mutex
gtk.threads_leave()
#Delaying 100ms until the next iteration
time.sleep(0.1)
def stop(self):
"""Stop method, sets the event to terminate the thread's main loop"""
self.stopthread.set()
class SampleGUI:
def destroy(self,widget,data=None):
global fs
fs.stop()
gtk.main_quit()
def get_relative_filename(self, filename):
f_parts = filename.split('/')
return f_parts[len(f_parts) - 1]
def browse(self,widget):
chooser1 = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
chooser1.set_show_hidden(True)
response1 = chooser1.run()
if response1 == gtk.RESPONSE_OK:
global filename1
filename1 = chooser1.get_filename()
self.textbox.set_text(filename1)
print filename1
elif response1 == gtk.RESPONSE_CANCEL:
chooser1.destroy()
chooser1.destroy()
def ensure_bucket(self,connection, bucket, canned_acl=None):
bucket_instance = None
try:
print 'Checking bucket:', bucket
bucket_instance = connection.get_bucket(bucket)
except S3ResponseError, s3error:
s3error_string = '%s' % s3error
if s3error_string.find('404') >= 0:
try:
bucket_instance = self.create_bucket(connection, bucket,
canned_acl)
except S3CreateError:
print 'Unable to create bucket %s' % bucket
message1 = gtk.MessageDialog(type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_OK)
msgg = "Unable to create bucket "+bucket
message1.set_markup(msgg)
message1.run()
message1.destroy()
elif s3error_string.find('403') >= 0:
message1 = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK)
msgg = "You do not have permission to access bucket"
message1.set_markup(msgg)
message1.run()
message1.destroy()
d.hide()
d.destroy()
print 'You do not have permission to access bucket:', bucket
else:
print s3error_string
sys.exit()
return bucket_instance
def upload_file(self,bucket_instance, filename,
canned_acl=None):
fs = FractionSetter()
global fs
fs.start()
print 'Uploading file'
print "file name",filename
k = Key(bucket_instance)
k.key = self.get_relative_filename(filename)
m_file = open(filename, 'rb')
print filename
try:
k.set_contents_from_file(m_file,policy=canned_acl)
fs.stop()
except S3ResponseError, s3error:
s3error_string = '%s' % s3error
if s3error_string.find('403') >= 0:
print 'Permission denied while writing:', k.key
else:
print s3error_string
sys.exit()
def submitt(self,widget):
print "submitt"
global filename1
print "file name",filename1
conn = boto.s3.connection.S3Connection(
aws_access_key_id='WKy3rMzOWPouVOxK1p3Ar1C2uRBwa2FBXnCw',
aws_secret_access_key='UmMJCdlCXvW9DJOgN2MkTOmEXJJKcQu62bFWg',
is_secure=False,
host="10.184.39.113",
port=8773,
calling_format=boto.s3.connection.OrdinaryCallingFormat(),
path='/services/Walrus',
)
print conn
bucket_instance = self.ensure_bucket(conn, "sample", canned_acl=None)
print bucket_instance
self.upload_file(bucket_instance, filename1, canned_acl=None)
def pageChanged(self,notebook,page,page_num):
print "ClickedMe called for"
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
self.window.set_size_request(600,400)
self.window.set_title("UPLOAD A OBJECT TO S3")
self.window.set_resizable(False)
self.button1 = gtk.Button("Browse")
self.button1.connect("clicked",self.browse)
self.button2 = gtk.Button("Submit")
self.button2.connect("clicked",self.submitt)
self.textbox = gtk.Entry()
self.label1 = gtk.Label("<b>Upload objects to S3</b>")
self.label1.set_use_markup(True)
self.table = gtk.Table(5, 5, True)
notebook = gtk.Notebook()
notebook.set_tab_pos(gtk.POS_TOP)
notebook.connect("switch-page",self.pageChanged)
page1 = gtk.Frame(label=None)
self.table.attach(self.label1, 1, 4, 1, 2)
self.table.attach(self.textbox, 1, 4, 2, 3)
self.table.attach(self.button1, 4, 5, 2, 3, xpadding=20, ypadding=20)
self.table.attach(self.button2, 4, 5, 3, 4,xpadding=20, ypadding=20)
global progressbar
progressbar = gtk.ProgressBar()
self.table.attach(progressbar, 0, 5, 4, 5, xpadding=20, ypadding=20)
page1.add(self.table)
notebook.append_page(page1,gtk.Label('Upload Files'))
self.window.add(notebook)
self.window.show_all()
self.window.connect("destroy",self.destroy)
def main(self):
gtk.main()
fs = FractionSetter()
global fs
fs.start()
if __name__ == "__main__":
base = SampleGUI()
base.main()
This might help
Follow the Pygtk FAQ http://faq.pygtk.org/index.py?req=show&file=faq23.020.htp
You might have to add following two lines in your code to continue the main iteration
while gtk.events_pending():
gtk.main_iteration()

How do I use multiple threads with PySide and Twython?

I'm trying to write a small python app, using PySide for the GUI and Twython as a Twitter API library, to catch a stream from Twitter.
The problem that I am having is that when I click "Start Monitoring Twitter" button, the UI freezes until the stream is complete, at which point the code continues to execute and disables the Start button and enables the Stop button. Here's the UI:
Everything else seems to work -- if I leave it, then the CSV file is created as I suspect -- the Twython components seem to be working as expected.
Line 151 is where the streaming from Twitter is engaged when I click start:
self.stream.statuses.filter(track=self.search_term)
How can I move the streaming to a separate thread and then use the Stop button on the UI to tell Twython to complete capturing the stream and exit?
I need to be able to send the MyStreamer instance to another thread and then send it the .disconnect() signal to have it terminate capturing the stream.
Here's the full code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import platform
import PySide
from PySide.QtGui import QApplication, QMainWindow, QPushButton, QCheckBox, QTextEdit
from time import sleep
from ui_tweetstream import Ui_MainWindow
from twython import Twython
from twython import TwythonStreamer
import csv
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
# Set up Variables
self.tweet_fav_count = True
self.tweet_geocoordinates = True
self.tweet_id = True
self.tweet_language = True
self.tweet_orig_tweet_id = True
self.tweet_orig_username = True
self.tweet_retweeted = True
self.tweet_sensitive = True
self.tweet_source_app = True
self.tweet_timestamp = True
self.tweet_user_name = True
self.search_term = "#bigdata"
self.tweets_to_get = 1000
# Bind the interface
self.check_tweet_fav_count.clicked.connect(self.setTweetFavCount)
self.check_tweet_geocoordinates.clicked.connect(self.setTweetGeocoordinates)
self.check_tweet_id.clicked.connect(self.setTweetID)
self.check_tweet_language.clicked.connect(self.setTweetLanguage)
self.check_tweet_orig_tweet_id.clicked.connect(self.setTweetOrigTweetID)
self.check_tweet_orig_username.clicked.connect(self.setTweetOrigUsername)
self.check_tweet_retweeted.clicked.connect(self.setTweetRetweeted)
self.check_tweet_sensitive.clicked.connect(self.setTweetSensitive)
self.check_tweet_source_app.clicked.connect(self.setTweetSourceApp)
self.check_tweet_timestamp.clicked.connect(self.setTweetTimestamp)
self.check_tweet_user_name.clicked.connect(self.setTweetUsername)
self.button_start.clicked.connect(self.streamStart)
self.button_stop.clicked.connect(self.streamStop)
# Set the initial states
self.button_stop.setEnabled(False)
APP_KEY = ''
APP_SECRET = ''
OAUTH_TOKEN = ''
OAUTH_TOKEN_SECRET = ''
self.t = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
self.stream = MyStreamer(APP_KEY,APP_SECRET,OAUTH_TOKEN,OAUTH_TOKEN_SECRET)
self.stream.init_mainWindow(self)
def streamStop(self):
print "Stopping stream"
# Enable other controls here
self.button_stop.setEnabled(False)
self.button_start.setEnabled(True)
self.setControlStates(True)
self.stream.stopStream()
def setControlStates(self, state):
self.check_tweet_fav_count.setEnabled(state)
self.check_tweet_geocoordinates.setEnabled(state)
self.check_tweet_id.setEnabled(state)
self.check_tweet_language.setEnabled(state)
self.check_tweet_orig_tweet_id.setEnabled(state)
self.check_tweet_orig_username.setEnabled(state)
self.check_tweet_retweeted.setEnabled(state)
self.check_tweet_sensitive.setEnabled(state)
self.check_tweet_source_app.setEnabled(state)
self.check_tweet_timestamp.setEnabled(state)
self.check_tweet_user_name.setEnabled(state)
self.search_box.setEnabled(state)
self.num_tweets_box.setEnabled(state)
# Functions for determining what to track
def setTweetFavCount(self):
self.tweet_fav_count = not self.tweet_fav_count
print "tweet_fav_count:", self.tweet_fav_count
def setTweetGeocoordinates(self):
self.tweet_geocoordinates = not self.tweet_geocoordinates
print "tweet_geocoordinates:", self.tweet_geocoordinates
def setTweetID(self):
self.tweet_id = not self.tweet_id
print "tweet_id:", self.tweet_id
def setTweetLanguage(self):
self.tweet_language = not self.tweet_language
print "tweet_language:", self.tweet_language
def setTweetOrigTweetID(self):
self.tweet_orig_tweet_id = not self.tweet_orig_tweet_id
print "tweet_orig_tweet_id:", self.tweet_orig_tweet_id
def setTweetOrigUsername(self):
self.tweet_orig_username = not self.tweet_orig_tweet_id
print "tweet_orig_username:", self. tweet_orig_username
def setTweetRetweeted(self):
self.tweet_retweeted = not self.tweet_retweeted
print "tweet_retweeted:", self.tweet_retweeted
def setTweetSensitive(self):
self.tweet_sensitive = not self.tweet_sensitive
print "tweet_sensitive:", self.tweet_sensitive
def setTweetSourceApp(self):
self.tweet_source_app = not self.tweet_source_app
print "tweet_source_app:", self.tweet_source_app
def setTweetTimestamp(self):
self.tweet_timestamp = not self.tweet_timestamp
print "tweet_timestamp:", self.tweet_timestamp
def setTweetUsername(self):
self.tweet_user_name = not self.tweet_user_name
print "tweet_user_name:", self.tweet_user_name
# Functions for starting and stopping the stream
def streamStart(self):
print "Starting stream"
self.setControlStates(False)
# Disable other controls here
self.button_start.setEnabled(False)
self.button_stop.setEnabled(True)
# Hack to try to disable the UI
# sleep(0.25)
# Get the active search term
self.search_term = self.search_box.text()
# Get the number of tweets
self.tweets_to_get = int(self.num_tweets_box.text())
# Set the streamer
self.stream.set_start_criteria(self.tweets_to_get)
self.stream.statuses.filter(track=self.search_term)
class MyStreamer(TwythonStreamer):
def init_mainWindow(self, the_main_window):
self.main_window = the_main_window
self.stop = False
self.header_done = False
def set_start_criteria(self, numTweets):
self.maxTweets = numTweets
self.tweetCount = 0
print "Number of tweets to get:", self.maxTweets
def stopStream(self):
self.stop = True
def on_success(self, data):
if 'text' in data:
self.tweetCount += 1
print "tweetCount:", self.tweetCount
#tweet = data['text'].encode('utf-8')
theTweet = data
writer = TweetMonkey()
writer.assignMainWindow(self.main_window, self.header_done)
self.header_done = True
writer.process(theTweet)
# Want to disconnect after the first result?
if self.stop is True or self.tweetCount >= self.maxTweets:
self.disconnect()
def on_error(self, status_code, data):
print status_code, data
class TweetMonkey:
def assignMainWindow(self,the_main_window, is_header_done):
self.main_window = the_main_window
self.header_done = is_header_done
def clean(self,text):
text = text.replace("\n","; ")
text = text.replace('"', "'")
text = text.replace(','," ")
return text
def create_header(self):
header = []
tweets = open("tweets.csv", 'ab+')
wr = csv.writer(tweets, dialect='excel')
if self.main_window.tweet_id is True:
header.append("id")
if self.main_window.tweet_language is True:
header.append("lang")
if self.main_window.tweet_user_name is True:
header.append("user_name")
header.append("tweet")
if self.main_window.tweet_retweeted is True:
header.append("retweeted")
if self.main_window.tweet_fav_count is True:
header.append("favorite_count")
if self.main_window.tweet_source_app is True:
header.append("source")
if self.main_window.tweet_orig_tweet_id is True:
header.append("in_reply_to_status_id")
if self.main_window.tweet_orig_username is True:
header.append("in_reply_to_screen_name")
# header.append("in_reply_to_user_id")
if self.main_window.tweet_sensitive is True:
header.append("possibly_sensitive")
if self.main_window.tweet_geocoordinates is True:
header.append("geo")
if self.main_window.tweet_timestamp is True:
header.append("created_at")
wr.writerow(header)
tweets.close()
def process(self, tweet):
if not self.header_done:
self.create_header()
self.header_done = True
# Create the file or append to the existing
theOutput = []
tweets = open("tweets.csv", 'ab+')
wr = csv.writer(tweets, dialect='excel')
if self.main_window.tweet_id is True:
theOutput.append(tweet['id'])
if self.main_window.tweet_language is True:
theOutput.append(tweet['lang'].encode('utf-8'))
if self.main_window.tweet_user_name is True:
theOutput.append(tweet['user']['name'].encode('utf-8', 'replace'))
theOutput.append(self.clean(tweet['text']).encode('utf-8', 'replace'))
if self.main_window.tweet_retweeted is True:
theOutput.append(tweet['retweeted'])
if self.main_window.tweet_fav_count is True:
theOutput.append(tweet['favorite_count'])
if self.main_window.tweet_source_app is True:
theOutput.append(self.clean(tweet['source']).encode('utf-8', 'replace'))
if self.main_window.tweet_orig_tweet_id is True:
theOutput.append(tweet['in_reply_to_status_id'])
if self.main_window.tweet_orig_username is True:
theOutput.append(tweet['in_reply_to_screen_name'])
#theOutput.append(tweet['in_reply_to_user_id'])
if self.main_window.tweet_sensitive is True:
if tweet.get('possibly_sensitive'):
theOutput.append(tweet['possibly_sensitive'])
else:
theOutput.append("False")
if self.main_window.tweet_geocoordinates is True:
if tweet['geo'] is not None:
if tweet['geo']['type'] == 'Point':
lat = str(tweet['geo']['coordinates'][0]) + " "
lon = str(tweet['geo']['coordinates'][1])
theOutput.append(lat + lon)
else:
theOutput.append(tweet['geo'])
else:
theOutput.append(tweet['geo'])
if self.main_window.tweet_timestamp is True:
theOutput.append(tweet['created_at'])
wr.writerow(theOutput)
tweets.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
frame = MainWindow()
frame.show()
app.exec_()
I know this is an old post but I ran into a similar problem in a simple app I recently wrote, my solution was to use threading.
I used the worker from:
https://pymotw.com/2/threading/
and the method described in:
http://aadrake.com/using-twitter-as-a-stream-processing-source.html
Basically running the Twython stream as a separate thread feeding text to a queue then I run the rest of the program in a separate loop reading from the queue.

Categories

Resources