I apologize for my bad English.
I need your help. I just bring strategy design pattern, I have understood the pattern with a simple example, but the implementation in my project is very confusing for me, maybe you can help me.
I have for example these two classes:
from tkinter import *
from app.interface.settings import New_Font
from app.controller.interface_elements.button_controller import Button_controller
from app.controller.interface_elements.close_button_controller import Close_button_controller
class New_Button:
def __init__(self, insert_button_in_frame, text, width, position_X, position_Y, background_color, foreground_color, close_button_parameter):
self._number_types = {int, float}
self.set_frame (insert_button_in_frame)
self.set_text (text)
self.set_width (width)
self.set_position (position_X, position_Y)
self.set_color (background_color, foreground_color)
self.set_close_button_parameter (close_button_parameter)
if self.get_text() == 'Abbrechen':
self.controller = Close_button_controller(self.get_close_button_parameter())
else:
self.controller = Button_controller()
self.create_button ()
def create_button(self):
self.set_button(Button(self.get_frame(),
text=self.get_text(),
bg=self.get_background_color(),
fg=self.get_foreground_color(),
width=self.get_width(),
font=New_Font().get_defaultfont(),
command=lambda :self.controller.main_method()))
self.get_button().place(x=self.get_position_X(),
y=self.get_position_Y())
def set_button(self, button):
self._button = button
def get_button(self):
return self._button
def set_frame(self, insert_button_in_frame):
if type(insert_button_in_frame) == Frame:
self._frame = insert_button_in_frame
else: raise TypeError
def get_frame(self):
return self._frame
def set_text(self, text):
if type(text) == str:
self._text = text
else: raise TypeError()
def get_text(self):
return self._text
def set_width(self, width):
if type(width) in self._number_types:
self._width = width
else: raise TypeError
def get_width(self):
return self._width
def set_position(self, position_X , position_Y):
if type(position_X) in self._number_types and type(position_Y) in self._number_types:
self._position_X = position_X
self._position_Y = position_Y
else: raise TypeError
def get_position_X(self):
return self._position_X
def get_position_Y(self):
return self._position_Y
def set_color(self, background_color, foreground_color):
if type(background_color) == str and type(foreground_color) == str:
self._background_color = background_color
self._foreground_color = foreground_color
else: raise TypeError
def get_background_color(self):
return self._background_color
def get_foreground_color(self):
return self._foreground_color
def set_controller(self, controller):
self._controller = controller
def get_controller(self):
return self._controller
def set_info(self, search_for):
self._info = self.get_button().cget(search_for)
def get_info(self):
return self._info
def set_close_button_parameter(self, close_button_parameter):
self._close_button_parameter = close_button_parameter
def get_close_button_parameter(self):
return self._close_button_parameter
and
from app.gui.top_frame import *
from app.interface.settings import New_Font
from app.controller.interface_elements.radiobutton_controller import Radiobutton_controller
class New_Radiobutton:
def __init__(self, frame_to_insert_radiobutton, radiobutton_label, button_horizontal_position, button_vertical_position, radiobutton_group, radiobutton_value, crawled_radiobuttons):
self._number_types = {int, float}
self._allowed_group_types = {int, float, str}
self._values = {1,3,5}
self._disable = {3,4,5,6}
self.set_frame_to_insert_radiobutton (frame_to_insert_radiobutton)
self.set_radiobutton_label (radiobutton_label)
self.set_position (button_horizontal_position, button_vertical_position)
self.set_radiobutton_group (radiobutton_group)
self.set_radiobutton_value (radiobutton_value)
self.create_radiobutton()
self._radiobutton_controller = Radiobutton_controller(crawled_radiobuttons)
self.set_first_radiobutton_of_a_group()
def create_radiobutton(self):
self.set_radiobutton(Radiobutton(self.get_frame_to_insert_radiobutton(),
text=self.get_radiobutton_label(),
variable=self.get_radiobutton_group(),
value=self.get_radiobutton_value(),
font=New_Font().get_defaultfont(),
command= lambda : self._radiobutton_controller.main_method()))
self.get_radiobutton().place(x=self.get_button_horizontal_position(),
y=self.get_button_vertical_position())
def set_first_radiobutton_of_a_group(self):
if self.get_radiobutton_value() in self._values:
self.get_radiobutton().invoke()
if self.get_radiobutton_value() in self._disable:
self.get_radiobutton().config(state=DISABLED)
def get_frame_to_insert_radiobutton(self):
return self._frame_to_insert_radiobutton
def set_frame_to_insert_radiobutton(self, frame_to_insert_radiobutton):
if type(frame_to_insert_radiobutton) == tkinter.Frame:
self._frame_to_insert_radiobutton = frame_to_insert_radiobutton
else: raise TypeError(frame_to_insert_radiobutton +
' frame_to_insert_radiobutton i not from type tkinter.Frame')
def get_radiobutton_label(self):
return self._radiobutton_label
def set_radiobutton_label(self, radiobutton_label):
if type(radiobutton_label) == str:
self._radiobutton_label = radiobutton_label
else: raise TypeError(radiobutton_label +
' radiobutton_label is not from type string')
def get_button_horizontal_position(self):
return self._button_horizontal_position
def get_button_vertical_position(self):
return self._button_vertical_position
def set_position(self, button_horizontal_position, button_vertical_position):
if type(button_horizontal_position) and type(button_vertical_position) in self._number_types:
self._button_horizontal_position = button_horizontal_position
self._button_vertical_position = button_vertical_position
else: raise TypeError(button_horizontal_position + ' ' + button_vertical_position +
' button_horizontal_position or button_vertical_position or both is/are not from type number')
def get_radiobutton_group(self):
return self._radiobutton_group
def set_radiobutton_group(self, radiobutton_group):
if type(radiobutton_group) in self._allowed_group_types:
self._radiobutton_group = radiobutton_group
else: raise TypeError(radiobutton_group +
' radiobutton_group is not from type int/float or string')
def get_radiobutton_value(self):
return self._radiobutton_value
def set_radiobutton_value(self, radiobutton_value):
if type(radiobutton_value) in self._number_types:
self._radiobutton_value = radiobutton_value
else: raise TypeError(radiobutton_value +
'radiobutton_value is not from type number')
def get_radiobutton_controller(self, radiobutton_controller):
return self.get_radiobutton().cget(radiobutton_controller)
def set_radiobutton(self, radiobutton):
self._radiobutton = radiobutton
def get_radiobutton(self):
return self._radiobutton
both classes need 90% the same methods and I have 2 other methods where it is. how do I start encapsulating the changeable now? because the button, no matter if radio, checkbox or button, is only created with the create method
thank you for your help
I am running a small unittest to check the roman number converter. Here is my code :-
class RomConverter(object):
def __init__(self):
self.digital_mapping = {"M":1000, "D":500, "C":100, "L":50, "X":10, "V":5, "I":1}
def convert(self, rom_num):
value = 0
for char in rom_num:
val += self.digital_mapping[char]
return value
import unittest
class RomConverterTest(unittest.TestCase):
def settingUp(self):
print ("Creating a new RomConverter...")
self.cvt = RomConverter()
def tearDown(self):
print ("Destroying the RomConverter...")
self.cvt = None
def test_empty_num(self):
self.assertTrue(self.cvt.convert("") == 0)
self.assertFalse(self.cvt.convert("") > 0)
def test_no_rom_num(self):
self.assertRaises(TypeError,self.cvt.convert, None)
if __name__ == "__main__":
unittest.main()
But I am getting this message when I run the code :-
Traceback (most recent call last):
File "receipe2 - Copy.py", line 31, in test_empty_roman_numeral
self.assertTrue(self.cvt.convert_to_decimal("") == 0)
AssertionError: False is not true
I see two problems in your code.
First def settingUp(self): should be def setUp(self):
And the return of def convert(self, rom_num): is indented to much. In result the method does not return 0 incase of an empty string.
Here is a working version:
class RomConverter(object):
def __init__(self):
self.digital_mapping = {"M":1000, "D":500, "C":100, "L":50, "X":10, "V":5, "I":1}
def convert(self, rom_num):
value = 0
for char in rom_num:
value += self.digital_mapping[char]
return value
import unittest
class RomConverterTest(unittest.TestCase):
def setUp(self):
print ("Creating a new RomConverter...")
self.cvt = RomConverter()
def tearDown(self):
print ("Destroying the RomConverter...")
self.cvt = None
def test_empty_num(self):
self.assertTrue(self.cvt.convert("") == 0)
self.assertFalse(self.cvt.convert("") > 0)
def test_no_rom_num(self):
self.assertRaises(TypeError,self.cvt.convert, None)
if __name__ == "__main__":
unittest.main()
I created a simple server/client app using PyQt.But I got strange error:
here is my server side code:
#! /usr/bin/python
import sys
import socket
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtNetwork import *
HOST = '127.0.0.1'
PORT = 9991
SIZEOF_UINT32 = 4
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((HOST, PORT))
self.socket.listen(5)
self.worker = Worker(self.socket)
self.connect(self.worker, SIGNAL("received"), self.updateUi)
self.connect(self.worker, SIGNAL("finished()"), self.updateUi)
self.connect(self.worker, SIGNAL("terminated()"), self.updateUi)
# Create widgets/layout
self.browser = QTextBrowser()
self.selectButton = QPushButton('Close server')
layout = QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.selectButton)
self.setLayout(layout)
self.setWindowTitle("Server")
self.worker.start()
def updateUi(self, text):
self.browser.append(text)
class Worker(QThread):
def __init__(self,socket,parent = None):
super(Worker, self).__init__(parent)
self.socket = socket
self.dir = '/home/jacos/down/'
self.filename = '/home/jacos/down/hello'
def receiveFile(self):
self.conn, self.addr = self.socket.accept()
totalData = ''
while 1:
data = self.conn.recv(1024)
if not data: break
totalData += data
print totalData
if totalData.find('f') == 0:
name = totalData.strip()[1:]
self.filename = self.dir + name
print self.filename
else:
self.saveFile(totalData)
print self.filename
self.emit(SIGNAL("received"),QString("received a file"))
def saveFile(self,data):
f = open(self.filename,'wb')
print self.filename
f.write(data)
f.close()
self.conn.close()
def run(self):
while 1:
self.receiveFile()
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
When I run it,I got this:
Traceback (most recent call last):
File "/home/jacos/bin/tss.pyw", line 75, in run
self.receiveFile()
File "/home/jacos/bin/tss.pyw", line 61, in receiveFile
self.saveFile(totalData)
File "/home/jacos/bin/tss.pyw", line 66, in saveFile
f = open(self.filename,'wb')
TypeError: file() argument 1 must be encoded string without NULL bytes, not str
TypeError: updateUi() takes exactly 2 arguments (1 given)
The problem is all about self.filename.It seems I can't pass it with the correct value...
Here is my client side code:
#! /usr/bin/python
# -*- coding: utf8 -*-
import sys
import socket
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtNetwork import *
HOST = '127.0.0.1'
PORT = 9991
SIZEOF_UINT32 = 4
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
# Create widgets/layout
self.browser = QTextBrowser()
self.selectButton = QPushButton('Send a File')
self.connectButton = QPushButton("Connect")
self.connectButton.setEnabled(True)
layout = QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.selectButton)
layout.addWidget(self.connectButton)
self.setLayout(layout)
# Signals and slots for line edit and connect button
self.selectButton.clicked.connect(self.sendFileName)
self.connectButton.clicked.connect(self.connectToServer)
self.setWindowTitle("Client")
# Update GUI
def updateUi(self, text):
self.browser.append(text)
def sendFileName(self):
filename=QFileDialog.getOpenFileName(self, 'Open File', '.')
name = filename.split('/')[-1]
self.updateUi("Sent file name:" + name)
self.socket.sendall("f" + name)
self.socket.close()
self.connectToServer()
self.sendFile(filename,name)
def sendFile(self,filename,name):
self.socket.sendall(open(filename,'rb').read())
self.updateUi("Sent file:" + filename)
self.socket.close()
self.connectButton.setEnabled(True)
def connectToServer(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((HOST, PORT))
self.connectButton.setEnabled(False)
self.updateUi("Connected")
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
Thanks for any help.
You probably have a NULL byte (\0 or \x00) in self.filename and as the error indicates, you can't open a file with the name containing NULL byte. Deal with them appropriately beforehand (eg: remove, replace, etc.).
As for the other error: You are connecting two signals (finished and terminated) to self.updateUi. And these signals doesn't have pass any arguments whereas self.updateUi expects an argument to be passed, namely text. I'm not sure what your goal is but you might consider adding a default argument for the text parameter in self.updateUi.
I'm having trouble implementing a thread correctly to keep my application from locking up and experiencing weird behavior. The app is designed to log into a ubuntu based server or ubuntu embedded server and search for log files that may be in the clear. The embedded server works, but the app keeps locking up while the search is occurring. The siteserver will not process. I have yet to code the local file search. I would like to add a progress bar once I figure out how to implement threads. I thought this would be straight forward since I've been learning and working with Python for several months now, but working with a GUI has its challenges. I'm still a neophyte and open to all the criticisms; it only helps me to become a better programmer. Any help is greatly appreciated. Here is the code below:
#!c:\python27
import wx
import os
import re
import paramiko
import string
import fileinput
import os.path
import dircache
import sys
import time
import datetime, time
import wx
from wxGui import *
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame("SecureTool v2.0.0", (50, 60), (458, 332))
frame.Show()
self.SetTopWindow(frame)
return True
class MyFrame(wx.Frame):
def __init__(self, title, pos, size):
wx.Frame.__init__(self, None, -1, title, pos, size)
toolbar = self.CreateToolBar()
toolbar.Realize()
menuFile = wx.Menu()
menuFile.Append(1, "&About...")
menuFile.AppendSeparator()
menuFile.Append(2, "E&xit")
menuBar = wx.MenuBar()
menuBar.Append(menuFile, "&File")
menu2 = wx.Menu()
menu2.Append(wx.NewId(), "&Copy", "Copy in status bar")
menu2.AppendSeparator()
menu2.Append(wx.NewId(), "C&ut", "")
menu2.AppendSeparator()
menu2.Append(wx.NewId(), "Paste", "")
menu2.AppendSeparator()
menu2.Append(wx.NewId(), "&Options...", "Display Options")
menuBar.Append(menu2, "&Edit")
self.SetMenuBar(menuBar)
self.CreateStatusBar()
self.SetStatusText("Welcome to SecureTool!")
self.Bind(wx.EVT_MENU, self.OnAbout, id=1)
self.Bind(wx.EVT_MENU, self.OnQuit, id=2)
panel = wx.Panel(self)
panel.SetBackgroundColour('LIGHT GREY')
#Close button
button = wx.Button(panel, label="EXIT", pos=(229, 160), size=(229, 80))
self.Bind(wx.EVT_BUTTON, self.OnQuit, button)
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
#Embed Server button
button2 = wx.Button(panel, label="Embed Server", pos=(0, 160), size=(229, 80))
self.Bind(wx.EVT_BUTTON, self.OnIP, button2)
#Site Server
button3 = wx.Button(panel, label="SITESERVER", pos=(0, 80), size=(229, 80))
self.Bind(wx.EVT_BUTTON, self.OnUsrPswd, button3)
#Local Search
button4 = wx.Button(panel, label="LOCAL SEARCH", pos=(229, 80), size=(229, 80))
self.Bind(wx.EVT_BUTTON, self.OnOpen, button4)
EVT_RESULT(self, self.OnResult)
self.worker = None
def OnIP(self, event):
ip_address = 0
result = ''
dlg = wx.TextEntryDialog(None, "Enter the IP Address.",
'Embed Server Connect', 'xxx.xxx.xxx.xxx')
if dlg.ShowModal() == wx.ID_OK:
ip_address = dlg.GetValue()
if ip_address:
cmsg = wx.MessageDialog(None, 'Do you want to connect to: ' + ip_address,
'Connect', wx.YES_NO | wx.ICON_QUESTION)
result = cmsg.ShowModal()
if result == wx.ID_YES:
self.DispConnect(ip_address)
cmsg.Destroy()
dlg.Destroy()
return True
def OnUsrPswd(self, event):
passwrd = 0
result = ''
result = wx.TextEntryDialog(None, 'Enter Weekly Password', 'Site Server login','')
if result.ShowModal() == wx.ID_OK:
passwrd = result.GetValue()
if passwrd:
psmsg = wx.MessageDialog(None, 'Do you want to connect to the Siteserver?', 'Connect',
wx.YES_NO | wx.ICON_QUESTION)
result = psmsg.ShowModal()
if result == wx.ID_YES:
self.SiteserverConnect(passwrd)
psmsg.Destroy()
result.Destroy()
return True
def ErrMsg(self):
ermsg = wx.MessageDialog(None, 'Invalid Entry!', 'ConnectionDialog', wx.ICON_ERROR)
ermsg.ShowModal()
ermsg.Destroy()
def GoodConnect(self):
gdcnt = wx.MessageDialog(None, 'You are connected!', 'ConnectionStatus', wx.ICON_INFORMATION)
gdcnt.ShowModal()
#if gdcnt.ShowModal() == wx.ID_OK:
gdcnt.Destroy()
def OnFinish(self):
finish = wx.MessageDialog(None, 'Job is finished!', 'WorkStatus', wx.ICON_INFORMATION)
finish.ShowModal()
finish.Destroy()
def DispConnect(self, address):
pattern = r"\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"
port = 22
user = 'root'
password ='******'
if re.match(pattern, address):
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(address,port,user,password)
Ssh = ssh
self.GoodConnect()
self.OnSearch(Ssh)
else:
self.ErrMsg()
def SiteserverConnect(self, password):
port = 22
user = 'root2'
address = '10.5.48.2'
if password:
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(address,port,user,password)
Ssh = ssh
self.GoodConnect()
self.OnSiteSearch(Ssh)
else:
self.ErrMsg()
def startWorker(self,a, b, c):
self.button2.Disable()
self.thread = Thread(target=self.LongRunningSearch)
self.thread.start()
def OnSearch(self, sssh):
self.startWorker(self.OnFinish, self.LongRunningSearch, wargs=[sssh])
self.OnFinish()
def LongRunningSearch(sssh):
ssh = sssh
apath = '/'
apattern = '"*.txt" -o -name "*.log"'
rawcommand = 'find {path} -name "*.txt" -o -name "*.log"'
command1 = rawcommand.format(path=apath, pattern=apattern)
stdin, stdout, stderr = ssh.exec_command(command1)
filelist = stdout.read().splitlines()
ftp = ssh.open_sftp()
for afile in filelist:
(head, filename) = os.path.split(afile)
paths = '/dispenser_result.log'
temp = ftp.file(paths, 'w')
from time import strftime
temp.write("{0:^75}".format("Company -Security Report" ) + strftime(" %Y-%m-%d %H:%M:%S") + "\n\n")
ustring = wx.TextEntryDialog(None, 'Enter a search string below:', 'Search', 'String Name')
if ustring.ShowModal() == wx.ID_OK:
userstring = ustring.GetValue()
if userstring:
userStrHEX = userstring.encode('hex')
userStrASCII = ''.join(str(ord(char)) for char in userstring)
regex = re.compile(r"(%s|%s|%s)" % ( re.escape( userstring ), re.escape( userStrHEX ), re.escape( userStrASCII )))
else:
sys.exit('You Must Enter A String!!!')
count = 0
for afile in filelist:
(head, filename) = os.path.split(afile)
if afile.endswith(".log") or afile.endswith(".txt"):
f=ftp.open(afile, 'r')
for i, line in enumerate(f.readlines()):
result = regex.search(line)
if result:
count += 1
ln = str(i)
pathname = os.path.join(afile)
template = "\n\nLine: {0}\nFile: {1}\nString Type: {2}\n\n"
output = template.format(ln, pathname, result.group())
ftp.get(afile, 'c:\\Extracted\\' + filename)
temp.write(output)
break
else:
#print "No Match in: " + os.path.join(afile)
temp.write("\nNo Match in: " + os.path.join(afile))
f.close()
for fnum in filelist:
#print "\nFiles Searched: ", len(filelist)
#print "Files Matched: ", count
num = len(filelist)
temp.write("\n\nFiles Searched:" + '%s\n' % (num))
temp.write("Files Matched:"+ '%s\n' % (count))
temp.write("Search String:"+ '%s\n' % (userstring))
break
temp.close()
defaultFolder = "DispenserLogResults"
if not defaultFolder.endswith(':') and not os.path.exists('c:\\Extracted\\DispenserLogResults'):
os.mkdir('c:\\Extracted\\DispenserLogResults')
else:
pass
ftp.get(paths, 'c:\\Extracted\\DispenserLogResults\\dispenser_result.log')
ftp.remove(paths)
re.purge()
ftp.close()
ssh.close()
def OnSiteSearch(self, sssh):
ssh = sssh
apath = '/var/log/apache2 /var/opt/smartmerch/log/'
apattern = '"*.log"'
rawcommand = 'find {path} -type f -name "*.log"'
command1 = rawcommand.format(path=apath, pattern=apattern)
stdin, stdout, stderr = ssh.exec_command(command1)
filelist = stdout.read().splitlines()
ftp = ssh.open_sftp()
for afile in filelist:
(head, filename) = os.path.split(afile)
paths = '/var/tmp/siteserver_result.log'
temp = ftp.file(paths, 'w')
from time import strftime
temp.write("{0:^75}".format("Gilbarco - SQA Security Report" ) + strftime(" %Y-%m-%d %H:%M:%S") + "\n\n")
temp.write("\n{0:^75}".format("SiteServer Logs" ))
ustring = wx.TextEntryDialog(None, 'Enter a search string below:', 'Search', 'String Name')
if ustring.ShowModal() == wx.ID_OK:
userstring = ustring.GetValue()
if userstring:
userStrHEX = userstring.encode('hex')
userStrASCII = ''.join(str(ord(char)) for char in userstring)
regex = re.compile(r"(%s|%s|%s)" % ( re.escape( userstring ), re.escape( userStrHEX ), re.escape( userStrASCII )))
else:
sys.exit('You Must Enter A String!!!')
count = 0
for afile in filelist:
(head, filename) = os.path.split(afile)
if afile.endswith(".log") or afile.endswith(".txt"):
f=ftp.open(afile, 'r')
for i, line in enumerate(f.readlines()):
result = regex.search(line)
if result:
count += 1
ln = str(i)
pathname = os.path.join(afile)
template = "\n\nLine: {0}\nFile: {1}\nString Type: {2}\n\n"
output = template.format(ln, pathname, result.group())
ftp.get(afile, 'c:\\Extracted\\' + filename)
temp.write(output)
break
else:
temp.write("\nNo Match in: " + os.path.join(afile))
f.close()
for fnum in filelist:
num = len(filelist)
temp.write("\n\nFiles Searched:" + '%s\n' % (num))
temp.write("Files Matched:"+ '%s\n' % (count))
temp.write("Search String:"+ '%s\n' % (userstring))
break
temp.close()
defaultFolder = "SiteServerLogResults"
if not defaultFolder.endswith(':') and not os.path.exists('c:\\Extracted\\SiteServerLogResults'):
os.mkdir('c:\\Extracted\\SiteServerLogResults')
else:
pass
ftp.get(paths, 'c:\\Extracted\\SiteServerLogResults\\siteserver_result.log')
ftp.remove(paths)
re.purge()
ftp.close()
ssh.close()
self.OnFinish()
def OnOpen(self,e):
self.dirname = ''
dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", wx.OPEN)
if dlg.ShowModal() == wx.ID_OK:
self.filename = dlg.GetFilename()
self.dirname = dlg.GetDirectory()
f = open(os.path.join(self.dirname, self.filename), 'r')
self.control.SetValue(f.read())
f.close()
dlg.Destroy()
def OnQuit(self, event):
self.Close(True)
def OnAbout(self, event):
wx.MessageBox("This is sQAST v2.0.0",
"About secureTool", wx.OK | wx.ICON_INFORMATION, self)
def OnCloseWindow(self, event):
self.Destroy()
if __name__ == '__main__':
app = MyApp(False)
app.MainLoop()
Traceback Error after running:
Traceback (most recent call last):
File "C:\SQA_log\wxGui.py", line 87, in OnIP
self.DispConnect(ip_address)
File "C:\SQA_log\wxGui.py", line 143, in DispConnect
self.OnSearch(Ssh)
File "C:\SQA_log\wxGui.py", line 169, in OnSearch
self.startWorker(self.OnFinish, self.LongRunningSearch, wargs=[sssh])
In your particular case I would do something like:
1) Encapsulate the long task and separate it from the GUI reaction, simplify your method:
def OnSearch(self, sssh):
self.LongRunningSearch(sssh) # Move all the blocking code here,
# just NOT the GUI reaction !
# Meaning self.OnFinish()...
self.OnFinish()
2) Verify that it still runs fine. Then modify the method to add the thread:
def OnSearch(self, sssh):
startWorker(self.OnFinish, self.LongRunningSearch, wargs=[sssh])
self.OnSearch will end immediately and self.OnFinish will be called after the thread running self.LongRunningSearch has finished. It may still need some tuning as I am unable to run your code on my computer.
I don't see any threading in your application at all. Whenever you make a call to something that will take a while, that something needs to run in a separate thread or it will block the main loop of your GUI.
You should read the following wiki entry on threading in wxPython: http://wiki.wxpython.org/LongRunningTasks
I have used the information therein to successfully create threaded wxPython applications. There's also a simple threading tutorial here: http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/
Hope that helps. If you get stuck, you should post to the official wxPython mailing group: https://groups.google.com/forum/#!forum/wxpython-users Those guys will set you straight.
You can also have a look at convenience module for threading implemented in the wx, wx.lib.delayedresult. It is very easy to use and to add when you find it is needed. I am not sure why it is ignored so often. I have written an example which uses it some time ago here.
It basically needs you to create two functions / methods. First, which will be ran in another thread, and second, which will be ran after another thread finishes. Then you just call startWorker(LongTaskDone, LongTask).
Example 1: Using wx.lib.delayedresult. wx.CallAfter is used to show progress in GUI thread using gauge widget. Official Documentation.
from time import sleep
import wx
from wx.lib.delayedresult import startWorker
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.startButton = wx.Button(self.panel, label="Long Task")
self.abortButton = wx.Button(self.panel, label="Abort")
self.abortButton.Disable()
self.gauge = wx.Gauge(self.panel, size=(-1, 20))
self.shouldAbort = False
self.startButton.Bind(wx.EVT_BUTTON, self.OnStartButton)
self.abortButton.Bind(wx.EVT_BUTTON, self.OnAbortButton)
self.windowSizer = wx.BoxSizer()
self.windowSizer.Add(self.panel, 1, wx.ALL | wx.EXPAND)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.startButton)
self.sizer.Add(self.abortButton)
self.sizer.Add((10, 10))
self.sizer.Add(self.gauge)
self.border = wx.BoxSizer()
self.border.Add(self.sizer, 1, wx.ALL | wx.EXPAND, 5)
self.panel.SetSizerAndFit(self.border)
self.SetSizerAndFit(self.windowSizer)
self.Show()
def OnStartButton(self, e):
self.startButton.Disable()
self.abortButton.Enable()
startWorker(self.LongTaskDone, self.LongTask)
def OnAbortButton(self, e):
self.shouldAbort = True
def LongTask(self):
for a in range(101):
sleep(0.05)
wx.CallAfter(self.gauge.SetValue, a)
if self.shouldAbort:
break
return self.shouldAbort
def LongTaskDone(self, result):
r = result.get()
if r:
print("Aborted!")
else:
print("Ended!")
self.startButton.Enable()
self.abortButton.Disable()
self.shouldAbort = False
self.gauge.SetValue(0)
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
Example 2: Using standard threading module. In some cases this may be more "ugly". I would recommend using wx.lib.delayedresult. Official Documentation.
from time import sleep
from threading import Thread
import wx
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.startButton = wx.Button(self.panel, label="Long Task")
self.abortButton = wx.Button(self.panel, label="Abort")
self.abortButton.Disable()
self.gauge = wx.Gauge(self.panel, size=(-1, 20))
self.shouldAbort = False
self.thread = None
self.startButton.Bind(wx.EVT_BUTTON, self.OnStartButton)
self.abortButton.Bind(wx.EVT_BUTTON, self.OnAbortButton)
self.windowSizer = wx.BoxSizer()
self.windowSizer.Add(self.panel, 1, wx.ALL | wx.EXPAND)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.startButton)
self.sizer.Add(self.abortButton)
self.sizer.Add((10, 10))
self.sizer.Add(self.gauge)
self.border = wx.BoxSizer()
self.border.Add(self.sizer, 1, wx.ALL | wx.EXPAND, 5)
self.panel.SetSizerAndFit(self.border)
self.SetSizerAndFit(self.windowSizer)
self.Show()
def OnStartButton(self, e):
self.startButton.Disable()
self.abortButton.Enable()
self.thread = Thread(target=self.LongTask)
self.thread.start()
def OnAbortButton(self, e):
self.shouldAbort = True
def LongTask(self):
for a in range(101):
sleep(0.05)
wx.CallAfter(self.gauge.SetValue, a)
if self.shouldAbort:
break
wx.CallAfter(self.LongTaskDone, self.shouldAbort)
def LongTaskDone(self, r):
if r:
print("Aborted!")
else:
print("Ended!")
self.startButton.Enable()
self.abortButton.Disable()
self.shouldAbort = False
self.gauge.SetValue(0)
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
Note: threading.Lock may be needed for thread-safe passing of more complicated variables and data than simple boolean flag.
Edit: Added examples.
Edit: Added ability to abort the thread.
Edit: Simplified the examples. Got rid of timer based on tom10's idea and also deleted threading.Lock as it is not needed here.
In wxPython, all calls to methods of GUI objects and event handlers need to happen in the main thread. Because of this, you need to be careful when using threading with wx, but it's usually easy to make the required modifications.
In your code, for example, you could do the call to wx.TextEntryDialog from the main thread, and then pass this information to the search thread.
If you need to request action of the GUI from the thread, the easiest way is to use wx.CallAfter, though there are other approaches that work as well.