I am making a GUI with tkinter that allows me to click a button that will run a port scan. I have a script for a port scan that functions correctly, I have managed to open the port scanner through the button on the GUI but then I receive an error that I otherwise don't receive when running the port scanner alone.
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Steve\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1550, in __call__
return self.func(*args)
File "<string>", line 51, in Scan
NameError: name 'IP_Input' is not defined
My code:
class CallWrapper:
"""Internal class. Stores function to call when some user
defined Tcl function is called e.g. after an event occurred."""
def __init__(self, func, subst, widget):
"""Store FUNC, SUBST and WIDGET as members."""
self.func = func
self.subst = subst
self.widget = widget
def __call__(self, *args):
"""Apply first function SUBST to arguments, than FUNC."""
try:
if self.subst:
args = self.subst(*args)
return self.func(*args) # THIS IS THE ERROR #
except SystemExit:
raise
except:
self.widget._report_exception()
class XView:
"""Mix-in class for querying and changing the horizontal position
of a widget's window."""
def xview(self, *args):
"""Query and change the horizontal position of the view."""
res = self.tk.call(self._w, 'xview', *args)
THIS IS THE CODE FOLLOWING FOR THE LINE 51 ERROR
def Scan():
print ('Scan Called.') #Debugging
IP = str(IP_Input.get(0.0, tkinter.END)) #THIS IS ERROR LINE 51#
print ("IP #Debugging")
Start = int(PortS.get(0.0, tkinter.END))
End = int(PortE.get(0.0, tkinter.END))
TestSocket = socket.socket()
CurrentPort = Start
OpenPorts = 0
print ('Starting scan...')
HowFar = int(CurrentPort/End * 100)
ProgText = HowFar, r'%'
Label1.config(text=('Percentage Done:', ProgText))
The problem is with your exec statement. You're opening your other .py file named port_scanner.py and then calling exec(open("./port scanner.py)).
This just isn't going to work.
Why this doesn't work:
When you do exec(open("path to .py file").read()) exec is of course executing this code, but the problem is that the global variables in this file aren't within the scope.
So, to make this work (which I don't recommend) you'd have to use:
exec(open(path).read(), globals())
From the documentation
If the globals dictionary does not contain a value for the key builtins, a reference to the dictionary of the built-in module builtins is inserted under that key. That way you can control what builtins are available to the executed code by inserting your own builtins dictionary into globals before passing it to exec().
If you really want to call your file this way then you should just use os.system.
Alternative approach:
You really don't need to call your file this way. You now have two instances of Tk() running. If you need another window then a widget is provided for this purpose. It is the Toplevel widget. You can restructure your code to create a Toplevel instance containing the port scanner app on your button click. An example being, create your port scanner app with the Toplevel widget (in your other file if you wish) then import the "app" into your file and on the button click have it initialize the app.
Additional Notes:
You're calling a while loop and if this runs (for any noticeable amount of time) then this is going to block the GUI's main event loop and causing your GUI to "hang".
Your first guess should not be that a part of the widely tested and used python standard library is flawed. The problem is (99.9% of the time)
while True:
print("In your own code.")
Related
lbox = Listbox
def Show():
Selected=lbox.get(lbox.curselection())
with open("pass.json","r+") as jfile:
try:
data=json.load(jfile)
for i in data['Details']:
if Selected==i["Site"]:
password_text.set(i["Password"])
uname_text.set(i["Username"])
except JSONDecodeError:
pass
I wanted to use curselection() but curselection() missing 1 required positional argument: 'self' is coming all the time
lbox was declared in another function which is given below
def Show_fun():
newWindow=Toplevel(window)
newWindow.title("Show your stuff")
newWindow.geometry("600x400")
Label(newWindow,text="Show passwords").grid(row=0,column=1,pady=10)
Label(newWindow,text="Site name : ").grid(row=1,pady=10)
lbox=Listbox(newWindow)
lbox.grid(row=1,column=2)
sites=[]
with open("pass.json","r+") as jfile:
try:
data=json.load(jfile)
for i in data['Details']:
sites.append(i["Site"])
except JSONDecodeError:
pass
lbox.config(height=lbox.size())
for i in sites:
lbox.insert(lbox.size(),i)
#site_entry = Entry(newWindow,textvariable = site_text,width=20,state=DISABLED).grid(row=1,column=2)
Label(newWindow,text="Username : ").grid(row=2,pady=10)
uname_entry=Entry(newWindow,textvariable=uname_text,state=DISABLED).grid(row=2,column=2)
Label(newWindow,text="Password : ").grid(row=3,pady=10)
pasword_entry=Entry(newWindow,textvariable=password_text,width=20,state=DISABLED).grid(row=3,column=2)
Button(newWindow,text="Show",command=Show,fg="#00FF00",bg="black",pady=10).grid(row=4,column=1)
I saw many YT vids . ListBox was working globally but in my its not working globally
EDIT: after giving parenthesis to ListBox() New error arises
Traceback (most recent call last):
File "C:\Program Files\Python38\lib\tkinter\__init__.py", line 1895, in __call__
return self.func(*args)
File "d:/Python files/cybersecurity/password manager/password_test.py", line 24, in Show
Selected=lbox.get(lbox.curselection())
File "C:\Program Files\Python38\l`enter code here`ib\tkinter\__init__.py", line 3190, in get
return self.tk.call(self._w, 'get', first)
_tkinter.TclError: bad listbox index "": must be active, anchor, end, #x,y, or a number
The error message simply means that the method was not invoked on the object but on the class instead. In the first code snippet, you didn't seem to instantiate a ListBox object.
You must change the line
lbox = Listbox
to something like:
# Tkinter window object
window = Tk()
# Create ListBox object and bind to the Tkinter window
lbox = Listbox(window)
In the above snippet, an instance of ListBox is created on which the method curselection() could be called. Give more emphasis to the argument passed to ListBox. The window variable used above is an instance of the Tk class which essentially constructs the Tkinter window. Without this argument, the listbox widget won't know which window it must bind to.
I've read at least 25 similar questions on this site, and I simply cannot get this working.
As it stands i'm just trying to build a simple chat app with a client and server. The GUI will be running on a separate thread to the logic to ensure things stay fluid and don't lock up. I've trimmed most of the logic out of the code to isolate the problem
import socket, csv, datetime, tkinter as tk, threading
from tkinter import ttk
interface = tk.Tk()
test = tk.StringVar()
test.set("String Var Test")
class serverInterface():
def __init__(self, interface):
global test
self.messageLog = tk.Text(interface, height=10, state="disabled", yscrollcommand="scrollBar.set")
self.scrollBar = ttk.Scrollbar(interface, command=self.messageLog.yview).grid(row=0, column=2, sticky="nsew")
self.messageLog.grid(row=0, column=0, columnspan=2)
test.trace("w", serverInterface.guiUpdate(self))
def guiUpdate(self):
self.messageLog.insert(tk.END, test)
class server():
def __init__(self):
global test
print("Server thread")
while True:
test.set("Updated from server object")
interface.title("Server")
serverInterface = threading.Thread(target=serverInterface(interface)) #Create serverInterface object
server = threading.Thread(target=server, daemon=True) # Create server object
server.start()
interface.mainloop()
This results in the console being spammed with Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\thoma\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__ return self.func(*args) TypeError: 'NoneType' object is not callable
I've also tried to make use of Queue() as I've seen others suggest, but that just results in a different set of errors and I feel using StringVar() is probably the better way of doing this.
I appreciate that there's probably some lines in this code that don't need to be there, they're just leftovers from all the different attempts at bodging it :/
Any solutions would be appreciated.
The error you're asking about is due to this line:
test.trace("w", serverInterface.guiUpdate(self))
That line is functionally identical to this:
result = serverInterface.guiUpdate(self)
test.trace("w", result)
Since guiUpdate(self) returns None, you're asking tkinter to call None. Hence the error TypeError: 'NoneType' object is not callable
The trace method must be given a callable (ie: a reference to a function). In this specific case you need to use self.guiUpdate.
The trace will automatically pass arguments to the function, so you need to properly define the function to accept those arguments. You also have a bug where you're trying to insert an object (test) in the text widget rather than the text contained in the object.
This is my first attempt at using the Tkinter plugin, I know very little past what tutorials I could find. All the answers I've seen so far put a class inside the py file that your building, I however have a plethora of tests that are already compiled into a Test class that runs many separate tests. All the tests run and no errors are encountered before trying to add to the ui.
I would like to be able to run each suite by clicking a button. My problem seems that I'm missing a step some where but not getting any errors or action when I click the button, but an error after I click and close the ui window. I should point out that importing the settings file (which contains most of the webdriver imports) does not help either. I get the same error.
Traceback:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python37\lib\tkinter\__init__.py", line 1702, in __call__
return self.func(*args)
File "C:\Python37\lib\unittest\case.py", line 663, in __call__
return self.run(*args, **kwds)
File "C:\Python37\lib\unittest\case.py", line 590, in run
testMethod = getattr(self, self._testMethodName)
AttributeError: 'Test' object has no attribute 'runTest'
My ui code:
import sys, os, tkinter, TESTadmin
top = tkinter.Tk()
a = TESTadmin.Test()
B = tkinter.Button(top, text= "Test Window", command=a )
B.pack()
top.mainloop()
for clarity my main test file:
from helpers.settings import *
from pieces import adminLogin, adminLogout, docs
class Test(unittest.TestCase):
def setUp(self):
# Maximize Window (remove quotes to use)
'''sel.maximize_window()'''
self.browser = webdriver.Firefox()
self.browser.get("https://mywebsite.net")
# We instantiate and start the browser
def testCases(self):# Add Tests Below
#log in to admin side
login = adminLogin.AdminLogin.do(self)
#docs page
docpage = docs.Docs.do(self)
#log out
logout = adminLogout.Logout.do(self)
if G.log:
for k in G.log.items():
print(k)
### Uncomment to close browser after test ###
def tearDown(self):
self.browser.close()
if __name__ == "__main__":
unittest.main()
As it would turn out, the answer like I thought is simple.
this line :
def testCases(self):
needs to read:
def runTest(self):
after that change every thing works percectly.
My confusion is because originally when building these tests I was following the directions here -> https://selenium-python.readthedocs.io/
They show you to use the testCases() method, and this works! Just not for calling the class. I didn't know where to put the function let alone know that Webdriver had a built in function other than what i was using.
I have a game I'm working on, using text to inform the user what's going on in the game. However, I'm using a Tkinter window to enable input with buttons, for a more professional feel. I also included a few labels, but they're all packing into a new window rather than the one I already made. Don't ask about variable names, but this is the code:
def scan():
action=str('scan')
TSGcontrols.destroy()
return action
def lookaround():
action=str('look around')
TSGcontrols.destroy()
return action
def visoron():
action=str('engage visor')
global firstvisor
if firstvisor==1:
firstvisor=int(0)
print ('The visor has a colour code.')
print ('It displays a wire frame over black, based on sensor data -\nallowing you to see through walls (to a degree).')
print ('\nColours:')
print ('Green = inert object')
print ('Blue = electrical signature')
print ('Red = weapon signature')
print ('Yellow = radiation (the darker the yellow, the deadlier exposure would be)')
print ('White = life (the more grey, the weaker the lifesigns. Dark grey is dead.)')
print ('Purple = unidentified\n')
TSGcontrols.destroy()
return action
def visoroff():
action=str('disengage visor')
TSGcontrols.destroy()
return action
def personbasecreate():
global TSGcontrols
TSGcontrols=tkinter.Tk(screenName='/TSGcontrols',baseName='/TSGcontrols',className='/TSGcontrols')
warning=Label(text='This is only the control panel for TSG.\nThe game\'s responses are output in the Python window.',bg='red')
global location
locationw=Label(text='Location: {0}'.format(location))
controlling=Label(text='You are controlling only yourself.',bg='blue',fg='white')
lookaround=Button(text='Look around',command=lookaround)
visoron=Button(text='Turn visor on',command=visoron)
visoroff=Button(text='Turn visor off',command=visoroff)
scan=Button(text='Scan',command=scan)
warning.pack(parent=TSGcontrols,side='top')
locationw.pack(parent=TSGcontrols,side='top')
controlling.pack(parent=TSGcontrols,side='top')
lookaround.pack(side='left')
scan.pack(side='left')
if visor=='on':
visoroff.pack(parent=TSGcontrols,side='right')
else:
visoron.pack(parent=TSGcontrols,side='right')
groupw.pack(parent=TSGcontrols,side='bottom')
Then later on:
addbutton1 = str('no')
while repeat==str('yes'):
time.sleep(3)
print ('\nChoose your action.')
# Creating the basic window:
personbasecreate()
if addbutton1=='yes':
# Adding the additional function:
leavequarters.pack(in_=personGUI,side='left')
action=str(personGUI.mainloop())
But instead of the widgets appearing in the window called 'TSG Controls', they appear in a new one called 'tk' - so when the window is destroyed to allow the variable 'action' to be processed, it's destroying an empty window and the game crashes because the functions are trying to destroy a window that isn't there, throwing the error:
Exception in Tkinter callback
Traceback (most recent call last):
File "D:\Python\lib\tkinter\__init__.py", line 1489, in __call__
return self.func(*args)
File "D:\Python\TSG.py", line 881, in lookaround
personGUI.destroy()
File "D:\Python\lib\tkinter\__init__.py", line 1849, in destroy
self.tk.call('destroy', self._w)
_tkinter.TclError: can't invoke "destroy" command: application has been destroyed
When the button 'Look around' is clicked twice.
Is there any way to fix this code, or a simpler way to do what I'm trying to accomplish here?
Part of the problem is probably this:
personGUI=tkinter.Tk(className='/TSG Controls')
warning=Label(text='This is only the control panel for TSG.\nThe game\'s responses are output in the Python window.',bg='red')
Notice that you are creating a new root window, but then you create a label without specifying a parent. You should always specify a parent for a widget, and you should always only ever create a single instance of Tk for your entire application. If you need to create more than one window, create your root window once, and then for other windows you need to create instances of tkinter.Toplevel.
I get an AttributeError I can't seem to work out.
I'm working with two classes.
The first class goes something like that.
class Partie:
def __init__(self):
# deleted lines
self.interface = Interface(jeu=self)
def evaluerProposition(self):
# computations
self.interface.afficherReponse()
Introducing second class (in a separate file).
class Interface:
def __init__(self, jeu):
self.jeu = jeu
self.root = tkinter.Tk()
# stuff
def onClick(self, event):
# talk
self.jeu.evaluerProposition()
def afficherReponse(self):
# stuff
I start the whole thing by
partie = Partie()
All manipulations on my widget work fine until some click event causes
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python33\lib\tkinter\__init__.py", line 1442, in __call__
return self.func(*args)
File "C:\Users\Canard\Documents\My Dropbox\Python\AtelierPython\Mastermind\classeInterface.py", line 197, in clic
self.jeu.evaluerProposition()
File "C:\Users\Canard\Documents\My Dropbox\Python\AtelierPython\Mastermind\classeJeu.py", line 55, in evaluerProposition
self.interface.afficherReponse()
AttributeError: 'Partie' object has no attribute 'interface'
I typed in the interpretor
>>> dir(partie)
and got a long list in return with 'interface' among the attributes.
Also typed
>>> partie.interface
<classeInterface.Interface object at 0x02C39E50>
so the attribute seems to exist.
Following the advice in some former post, I checked the instance names do not coincide with module names.
I am confused.
Most likely, in some code that you're not showing us, you're doing something like this:
self.some_button = tkinter.Button(..., command=self.interface.onClick())
Note the trailing () on onClick(). This would cause the onClick method to be called at the time the button is created, which is probably before your constructor is done constructing the instance of the Partie class.