I'm new for Programming and right now doing a small project for my Network Engineer job.
The whole idea of this app: input IP, MAC, username, password: and see prints from functions like:
logging to device!
gathering info
and etc
and show all this info real time in print_out = tkinter.Text box
Currently, I have 2 .py files:
MAC_search_GUI.py
MAC_search.py
MAC_search_GUI.py is a tkinter window where I can put in IP, MAC, username, and password + there is another window where I can see logs:
import tkinter
from tkinter import Button, Text
from tkinter import simpledialog
from MAC_search import MAC_search_func
def show_entry_fields():
IP = e1.get()
MAC = e2.get()
username = e3.get()
password = e4.get()
"""
e1.delete(0, tkinter.END)
e2.delete(0, tkinter.END)
e3.delete(0, tkinter.END)
e4.delete(0, tkinter.END)
"""
SESSION = {'ip': IP,
'device_type':'cisco_ios',
'username': username,
'password': password}
result = MAC_search_func(IP, MAC, **SESSION)
return print(result)
# f4b5.2fa0.8fca
root = tkinter.Tk()
tkinter.Label(root, text="IP:").grid(row=1)
tkinter.Label(root, text="MAC:").grid(row=2)
tkinter.Label(root, text="Username").grid(row=3)
tkinter.Label(root, text="Password").grid(row=4)
e1 = tkinter.Entry(root)
e2 = tkinter.Entry(root)
e3 = tkinter.Entry(root)
e4 = tkinter.Entry(root)
e1.grid(row=1, column=1)
e2.grid(row=2, column=1)
e3.grid(row=3, column=1)
e4.grid(row=4, column=1)
print_out = tkinter.Text(root, height = 20, width = 60, bg = "light cyan").grid(row=7, column=2)
tkinter.Button(root, text='Apply', command=show_entry_fields).grid(row=5, column=1, sticky=tkinter.W,
pady=4)
root.geometry("600x600")
root.mainloop()
The function MAC_search_func is located in MAC_search.py, connecting to input IP and collecting info about that device:
import netmiko
from netmiko import ConnectHandler
from netmiko.ssh_exception import NetMikoTimeoutException
from netmiko.ssh_exception import NetMikoAuthenticationException
from paramiko.ssh_exception import SSHException
def MAC_search_func(arg_ip, arg_mac, **arg_session):
def conv_Po_to_Int(arg_int):
JSON = connection.send_command("show etherchannel summary", use_textfsm=True)
for line in JSON:
if line['po_name'] == arg_int:
int_status = line['interfaces']
return int_status[0]
interface = ''
try:
connection = netmiko.ConnectHandler(**arg_session)
print("Connection is succefull")
except NetMikoTimeoutException:
return print(" #### Device is not reachable! ####")
except NetMikoAuthenticationException:
return print(" #### Wrong Username or Password! ####")
except SSHException:
return print(" #### Make sure SSH is enabled! ####")
# Looking for MAC in Mac address table
JSON = connection.send_command("show mac address-table", use_textfsm=True)
for line in JSON:
if line['destination_address'] == arg_mac:
interface = line['destination_port']
# Checking if interface is Port channel
if interface[0:2] == "Po":
interface = conv_Po_to_Int(interface)
# IF MAC is not found
if interface == '':
return print("This MAC-ADDRESS IS NOT FOUND ON THIS IP: "+ arg_ip)
# If Mac was found on switch checking if Int is Trunk or Access
JSON = connection.send_command("show interfaces status", use_textfsm=True)
for line in JSON:
if line['port'] == interface:
int_status = line['vlan']
# if port is trunk checking which device located on another end
if int_status == "trunk":
JSON = connection.send_command("show cdp neighbors " + interface, use_textfsm=True)
for line in JSON:
next_switch = line['neighbor']
JSON = connection.send_command("show cdp entry " + next_switch)
result = JSON.find('IP address:')
return print("Looks like this mac located on device with " + JSON[result:(result + 21)] + " and hostname: " + next_switch)
else:
return print("MAC was found on " + interface)
connection.disconnect()
So, I have a few issues with that:
I don't know how to send RETURN from my MAC_search function back to MAC_search_GUI, so I can print it with:
print_out = tkinter.Text(root, height = 20, width = 60, bg = "light cyan").grid(row=7, column=2)
When I pressing Apply, the app is NOt-responding until all functions will not be finished(5-10 seconds), because it takes time to connect and get info from switch. How to make that after i will click Apply, app will not wait until the end but just continue working, until Return will not show up in print_out window
Sorry Mast,
Solution is:
for my first problem:
result = MAC_search_func(IP, MAC, **SESSION)
return print_out.insert("end-1c", result)
For my second problem I did not found complete solution, but it working faster now.
This is my client:
from tkinter import *
import tkinter.simpledialog
import socket
import select
import ssl
import threading
Host = '127.0.0.1'
Port = 87
def create_connection():
return socket.create_connection((Host, Port))
def gui():
global e1
global txt
root = Tk()
root.title('Amifre chat')
root.geometry("700x515")
txt = Text(root, width=70, height=30)
txt.config(state=DISABLED)
e1 = Entry(root, width=93)
e1.place(x=0, y=487)
txt.place(x=0)
t = threading.Thread(target=display_msg())
t.daemon = True
root.after(1, t.start())
root.mainloop()
def display_msg():
r, w, x = select.select([client_socket], [], [], 0.00001)
if client_socket in r:
data = client_socket.recv().decode()
txt.config(state=NORMAL)
txt.insert(INSERT, data + '\n')
txt.config(state=DISABLED)
if __name__ == '__main__':
start = Tk()
b = Button(start, text='Click to join the chat', command=create_user_name).grid(row=0)
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
client_socket = create_connection()
client_socket = context.wrap_socket(client_socket, server_hostname='127.0.0.1')
start.mainloop()
gui()
This is a client for chat and the thread in the gui function call the display_msg function only once so does anyone have any idea why is it? (sending data works well and it dislplayed in client without GUI)
You should pass only the function name to target option, and call t.start() directly without using after():
t = threading.Thread(target=display_msg, daemon=True)
t.start()
Then, you need to use while loop inside display_msg() to keep receiving data from server:
def display_msg():
while True:
r, w, x = select.select([client_socket], [], [])
if client_socket in r:
data = client_socket.recv(1024).decode()
txt.config(state=NORMAL)
txt.insert(INSERT, data + '\n')
txt.config(state=DISABLED)
This code:
t = threading.Thread(target=display_msg())
is functionally identical to this code:
result = display_msg()
t = threading.Thread(result)
And this code:
root.after(1, t.start())
is functionally identical to this code:
result = t.start()
root.after(1, result)
In both threading.Thread and after, the values given to the functions must be references to a function rather than the result of a function (unless the result is itself a reference to a function).
t = threading.Thread(target=display_msg)
...
root.after(1, t.start)
Regardless, the answer to "why the thread runs only once?" is because that's what threads do. Threads run until they are done. If you need code to run in a loop, you will need to write the loop yourself.
I am developing a python program for reading ports. My script has a print for every open port checked. But I would like to remove this print and put it inside a class. For when the programmer wants to see print he calls the class.
I can create common classes to get user input from a main file (main.py) and run inside the script, but I can't control print from the main file
def ping(target,scale):
def portscan(port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
con = s.connect((target,port))
time.sleep(5)
port_print = 'Port :',port,"Is Open!."
time.sleep(5)
#python = sys.executable
#os.execl(python, python, * sys.argv)
print('Terminated')
con.close()
except:
#result = None
#return result
pass
r = 1
scal = int(scale)
for x in range(1,scal):
t = threading.Thread(target=portscan,kwargs={'port':r})
r += 1
t.start()
As you can see I created the variable port_print, and I would like that when the user called in the main file, there would be the print.
Use a Queueto get around return limitations in threads:
from queue import Queue
def ping(target,scale, queue):
def portscan(port, queue):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
con = s.connect((target,port))
time.sleep(5)
port_print = 'Port :',port,"Is Open!."
queue.put(port_print)
time.sleep(5)
#python = sys.executable
#os.execl(python, python, * sys.argv)
print('Terminated')
con.close()
except:
#result = None
#return result
pass
r = 1
scal = int(scale)
for x in range(1,scal):
t = threading.Thread(target=portscan,kwargs={'port':r, queue=queue})
r += 1
t.start()
def main():
my_queue = Queue()
target = 'some target'
scale = 10
ping(target, scale, my_queue)
random_port_print = my_queue.get()
print(random_port_print)
Not tested but prly pretty close to correct.
I have two files. Let's call it file_X.py and file_Y.py. Both have infinite loops that continuously read data from COM ports. I have a tkinter module with two buttons to launch file_X and file_Y. So if I click button A, I want file_X to run and button B would launch file_Y. How can I run these files in parallel and have them display the data in their respective command prompt terminals?
I tried using runpy and os.system. os.system would throw me an error even though the modules for both files were working fine on their own. On the other hand, runpy wouldn't let me click on the other button while the first module was running.
Tkinter module:
import tkinter as tk
import time
import runpy
root = tk.Tk()
root. title("App")
root.geometry('700x500')
v = tk.IntVar()
v.set(-1)
button_labels = [
(" Device 1 "),
(" Device 2 ")]
def ShowChoice():
choice = v.get() + 1
if(choice == 1):
runpy.run_module('file_X', run_name='__main__')
elif(choice == 2):
runpy.run_module('file_Y', run_name='__main__')
tk.Label(root,
text="""Choose the device you want to launch:""",
font = 'Arial 20 bold',
justify = tk.LEFT,
height = 6,
padx = 20).pack()
for val, button_label in enumerate(button_labels):
tk.Radiobutton(root,
text = button_label,
font = 'Times 12 bold',
indicatoron = 0,
bg = 'cornflower blue',
width = 40,
padx = 20,
pady = 5,
variable=v,
command=ShowChoice,
value=val).pack(anchor=tk.S)
root.mainloop()
file_X and file_Y have pretty much the same code but are connected to different COM Ports and have different string modifications.
import serial
import time
import csv
try:
ser = serial.Serial("COM4",
baudrate=2400,
bytesize=serial.EIGHTBITS,
parity =serial.PARITY_ODD)
except:
print("Device not detected")
def Reader():
global ser
try:
data = ser.readline().decode('utf-8')
data = str(data).replace("\r\n","")
data = data.replace("\x000","")
return data
except:
return "Data Unavailable"
def Start():
date_now = time.strftime('%d.%m.%y')
time_now = time.strftime('%H.%M.%S')
file_name = date_now + '__' + time_now + '.csv'
with open(file_name, 'w+') as f:
csv_file = csv.writer(f)
csv_file.writerow(['DATE','TIME','VALUE'])
while True:
date_now = time.strftime('%d/%m/%y')
time_now = time.strftime('%H:%M:%S')
data = Reader()
csv_file.writerow([date_now, time_now, data])
print([date_now, time_now, data])
if __name__ =='__main__':
Start()
You could use the threading, multiprocessing or subprocess modules.
Here is a quick sample which demonstrates the threading module.
import threading, time
def Start(name=''):
cnt=0
while(cnt<10):
cnt+=1
print "This is thread %s" % name
time.sleep(1)
thread1 = threading.Thread(target=Start, name='Thread-1', args=('Serial1',))
thread2 = threading.Thread(target=Start, name='Thread-2', args=('Serial2',))
thread2.start()
thread1.start()
while (thread1.isAlive() and thread2.isAlive()):
time.sleep(2)
print "Running Threads : %s" % [thread.name for thread in threading.enumerate()]
print "done"
As suggested you could import file_X and file_Y and create a thread for each using the Start() function as the target (callable object) to be invoked by the run() method of each thread.
import file_X, file_Y
thread1 = threading.Thread(target=file_X.Start, name='COM1')
thread2 = threading.Thread(target=file_Y.Start, name='COM2')
thread1.start()
thread2.start()
The multiprocessing module is similar to threading.
Alternatively run file_X and file_Y as subprocesses using the subprocess module.
NEW <<<<
Here is a solution using threading. I've only tested it with one port.
import threading
import time
import serial
import sys, os.path
import csv
def OpenSerialPort(port=""):
print ("Open port %s" % port)
serPort = None
try:
serPort = serial.Serial(port,
baudrate=2400,
bytesize=serial.EIGHTBITS,
parity =serial.PARITY_ODD)
except serial.SerialException as msg:
print( "Error opening serial port %s" % msg)
except:
exctype, errorMsg = sys.exc_info()[:2]
print ("%s %s" % (errorMsg, exctype))
return serPort
def Reader(file_name, serialPort, stopped):
print ("Start reading serial port %s." % serialPort.name)
serialPort.timeout = 1.0
while not stopped.is_set():
serData = ''
try:
#print "Reading port..."
serData = serialPort.readline()
except:
exctype, errorMsg = sys.exc_info()[:2]
print ("Error reading port - %s" % errorMsg)
stopped.set()
break
if len(serData) > 0:
serData = serData.decode('utf-8')
serData = str(serData).replace("\r\n","")
serData = serData.replace("\x000","")
Log_Data(file_name, serData)
#else:
# print("Reader() no Data")
serialPort.close()
print ("Reader finished. Closed %s" % serialPort.name)
def Init_Log(portName=''):
#Create log file
portName = os.path.basename(portName)
file_name = time.strftime('%d.%m.%y__%H.%M.%S') + "__%s.csv" % portName
with open(file_name, 'w') as f:
csv_file = csv.writer(f)
csv_file.writerow(['DATE','TIME','VALUE'])
return file_name
def Log_Data(file_name='', dataString=''):
date_now = time.strftime('%d/%m/%y')
time_now = time.strftime('%H:%M:%S')
with open(file_name, 'a') as f:
csv_file = csv.writer(f)
csv_file.writerow([date_now, time_now, dataString])
print([date_now, time_now, dataString])
if __name__ == "__main__":
stopped = threading.Event() # Create stopped event to notify all threads when it is time to stop.
#Open COM3 ports
portName = 'COM3'
serialPort_1 = OpenSerialPort(portName)
if serialPort_1 == None:
sys.exit(1)
file_name_1 = Init_Log(portName) #Create log file
p1 = threading.Thread(target=Reader, args=(file_name_1, serialPort_1, stopped,))
#Open COM4 ports
portName = 'COM4'
serialPort_2 = OpenSerialPort(portName)
if serialPort_2 == None:
sys.exit(1)
#Create log file
file_name_2 = Init_Log(portName)
p2 = threading.Thread(target=Reader, args=(file_name_2, serialPort_2, stopped,))
#Start port reader threads
p1.start()
p2.start()
#This is just a test loop that does nothing for awhile.
loopcnt = 20
while (loopcnt > 0) and (not stopped.is_set()):
loopcnt -= 1
print ("main() %d" % loopcnt)
try:
time.sleep(1)
except KeyboardInterrupt: #Capture Ctrl-C
print ("Captured Ctrl-C")
loopcnt=0
stopped.set()
stopped.set()
print ("Stopped")
p1.join()
p2.join()
serialPort_1.close()
serialPort_2.close()
print ("Done")
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.