Global variable is not defined - python

I'm trying to read a file with python, by posting the address in input line. In my plan, when I press the button, program will read the file, make all needed work with the text inside the first file, and write the result into a second one:
import Tkinter
class Generator(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent=parent
self.initialize()
def initialize(self):
self.grid()
self.addressLink = Tkinter.StringVar()
self.entry=Tkinter.Entry(self,textvariable=self.addressLink)
self.entry.grid(column=0,row=0,sticky='EW')
self.entry.bind("<Return>", self.OnPressEnter)
self.entry.bind(".", self.OnPressDot) # verify that address was accepted
self.addressLink.set(u"Enter your input file's address here!")
button=Tkinter.Button(self,text=u'Generate the list!',command=self.OnButtonClick)
button.grid(column=1,row=0)
self.labelVariable = Tkinter.StringVar()
label = Tkinter.Label(self, textvariable=self.labelVariable,
anchor="w",fg="white",bg="blue")
label.grid(column=0,row=1,columnspan=2,sticky='EW')
self.labelVariable.set(u"Enter Address !")
self.grid_columnconfigure(0,weight=1)
self.resizable(True,False)
def ProgramBody(readlink):
excelWrite=open('/Users/BUR/Desktop/final_TK.txt','w')
z=0
for index, line in enumerate(readlink, start=0):
keywrds=[]
title=line.split("+")
title=[lines.strip()for lines in title]
print title[0]
print index
header="Title"+"\t"+"Price equal to title:"+"\t"+"keyword1"+"\t"+"keyword2"+" \t"+"keyword3"+"\t"+"keyword4"+"\t"+"keyword5\t"+"Manufacturer Part Number\n"
exclWrt(header)
excelWrite.close()
def FileRead(tsink):
excelRead=open(tsink,'r')
print tsink
ProgramBody(tsink)
def OnButtonClick(self):
link=(self.addressLink.get())
# print link
self.labelVariable.set(link+" (Here is your button press!) ")
FileRead(link)
def OnPressEnter(self,event):
self.labelVariable.set(self.addressLink.get()+" (Here is your address!)")
def OnPressDot(self,event):
self.labelVariable.set(self.addressLink.get()+" (Here is your address!!!)")
if __name__=="__main__":
app=Generator(None)
app.title('Converter')
app.mainloop()
#excelRead=open('/Users/BUR/Desktop/listings/data.txt','r')
def exclWrt(typo):
excelWrite.write(typo)
Program runs, but when I press button it gives me:
> Exception in Tkinter callback Traceback (most recent call last):
> File
> "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py",
> line 1470, in __call__
> return self.func(*args) File "/Users/BUR/Documents/Python/Temp+price+keyw.1", line 114, in
> OnButtonClick
> FileRead(link) NameError: global name 'FileRead' is not defined
What did I miss?

You're using a class. First, you'll have an instance of the class passed to every function. Usually it's named self:
class A:
def something(self, my_arguments)
And, to call something from the class, you do this:
def something_else(self, another_arguments):
self.something(another_arguments)
The first argument will automatically be passed. Also, __init__ is called when you create an instance of your class, so you have no need of a separate initialize function.
I suggest you read more about classes here. This is just a very short solution for your problem.

Related

How do I use tklib widgets in tkinter?

I was looking for an IP address entry widget for tkinter for use with python3.7 and came across ipentry in the tklib.
https://core.tcl-lang.org/tklib/doc/trunk/embedded/www/tklib/files/modules/ipentry/ipentry.html#section2
This is not a terribly complicated need to 'recreate the wheel' for and there are several examples on stackoverflow for IP entry boxes but I'd really like to understand how to use the modules and widgets in the tklib with tkinter. Documentation or examples appear to be few and far between. Here's how far I've gotten:
First of all, I have to tell Python that this widget exists.
import tkinter as tk
root = tk.Tk()
root.tk.call(‘package’,’require’,’ipentry’)
Then I created a class for the widget.
class iPentry(tk.Widget):
def __init__(self, master):
tk.Widget.__init__(self, master, '::ipentry::ipentry’)
Then I create an instance of it and pack it in my window.
enterIp = iPentry(root)
enterIp.pack()
So far so good. I get a window with a familiar looking input box for an IPV4 address.
The problem is that I haven't figured out how to use the get or complete or insert widget commands. When I try to get from the enterIp widget that I created, I get an error.
myip = enterIp.get()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'iPentry' object has no attribute 'get'
I suspect that I'm missing some syntax concepts. Any suggestions for how to do this?
You need to define get() function in your wrapper class iPentry:
def get(self):
return self.tk.call(self._w, 'get')
Actually you need to define every functions that ipentry provides like above if you want to call them.
Thanks to acw1668 I was able to work through some bone headed mistakes and figure this out a bit. Here is some sample code for someone else who might like to work with these in Python. They are pretty limited and I found a few things that didn't work even though they are documented on the lib page. But they might be useful for some situations. The rdial in particular was surprising because it is visually a "thumbwheel" rather than a typical round dial. I have included a screenshot of what some of these look like in Macos.
This code displays an iPentry with a label below that will populate with the address when you press enter. Then there is a bank of 3 sliders whose values will show in a label below. Then an rdial whose value shows in a label below and finally a "voltmeter" that bounces around based on a random number. Enjoy.
# This Python file uses the following encoding: utf-8
# Python 3.7 and Tk version 8.6
import sys
import tkinter as tk
import random
class iPentry(tk.Widget):
def __init__(self, master):
tk.Widget.__init__(self, master, '::ipentry::ipentry')
def get(self):
return self.tk.call(self._w, 'get')
def complete(self):
return self.tk.call(self._w, 'complete')
class CWslider(tk.Widget):
def __init__(self, master, placeholder):
tk.Widget.__init__(self, master, '::controlwidget::slider',
{'variable':placeholder, 'from_':0, 'to':20, 'number':3,
'width':55, 'background':'yellow'})
def get(self):
getvalue = self.tk.call(self._w, 'get')
getvalue = [int(x) for x in getvalue]
return getvalue
def set(self, value):
self.tk.call(self._w, 'set', value)
def complete(self):
return self.tk.call(self._w, 'complete')
class CWrdial(tk.Widget):
def __init__(self, master):
tk.Widget.__init__(self, master, '::controlwidget::rdial',
{'width':50, 'orient':'vertical', 'height':100, 'background':'green'})
def get(self):
return self.tk.call(self._w, 'get')
def complete(self):
return self.tk.call(self._w, 'complete')
class CWvoltmeter(tk.Widget):
def __init__(self, master, variable):
tk.Widget.__init__(self, master, '::controlwidget::voltmeter',
{'min':0, 'max':100, 'variable':variable})
def getIP(event):
myip = enterIp.get()
labelvar.set(myip)
print(f"myip is {myip}")
def updating(master, myValuesvar, myvoltvar, interval):
#we can't get value from placeholder because slider corrupts the IntVar?
slidervalues = slider.get() #so we use the get method
myValuesvar.set(slidervalues)
mydialvalue.set(mydial.get())
myvoltvar.set( random.randrange(0, 100, 1))
root.after(interval, updating, root, myValuesvar, myvoltvar, interval)
root = tk.Tk()
root.geometry("300x550+280+0")
root.tk.call('package','require','ipentry')
root.tk.call('package','require','controlwidget')
enterIp = iPentry(root)
enterIp.pack()
labelIP = tk.Label(root, text="Show The IP")
labelIP.pack()
labelvar = tk.StringVar()
label2 = tk.Label(root, textvariable=labelvar)
label2.pack()
root.bind('<Return>', getIP)
myvalues = [5,15,3]
myValuesvar = tk.IntVar()
placeholder = tk.IntVar() #necessary for slider to change values
slider = CWslider(root, placeholder)
slider.pack()
slider.set(myvalues)
labelSlider = tk.Label(root, textvariable=myValuesvar)
labelSlider.pack()
mydialvalue = tk.StringVar()
mydial = CWrdial(root)
mydial.pack()
labeldial = tk.Label(root, textvariable=mydialvalue)
labeldial.pack()
myvoltvar = tk.IntVar()
myvolt = CWvoltmeter(root, myvoltvar)
myvolt.pack()
interval = 300 #milliseconds for GUI
updating(root, myValuesvar, myvoltvar, interval)
root.mainloop()
sys.exit()

Calling methods from outside a class in Python - Tkinter events

I want to call a method in another class and make changes to the parent class when the button is clicked in Python. To explain; With Tkinter visual programming, I click the button to change the main window and I can not change the properties in the main window with another class method.
I get the error message below.
Exception in Tkinter callback Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/_ init _.py", line 1553, in _
call _
return self.func(*args) TypeError: buton_goster() missing 1 required positional argument: 'event'
class Butonol(object): #Button class
def __init__(self):
...
def buton_goster(self, event ): # Properties kisminda ozellik gosterir
Test.countshow = Test.countshow + 1;
if(Test.countshow >1):
Test.props0.pack_forget()
Test.props.pack_forget()
...
And here is the Test Class
class Test(Frame):
countshow = 0
...
def new_Button(self):
self.nesne = Butonol()
self.but= Button(self.mainFrame,text = self.nesne.text)
self.but.bind('<Button-1>',Butonol.buton_goster)
self.but.bind('B1-Motion>',self.label_tasi)
self.but.pack(side = LEFT,anchor = N)
Butonol.butonsay = Butonol.butonsay + 1
Butonol.butonliste.append(self.but)
The error is correct,
When you do you bind, you do not pass on the event, you simply add the function pointer.
If the buton_goster does not need "event" you should remove it or you should provide event as input when calling the function.

button command option in tkinter

In the little GUI app below. When I use button's command option to call a function. It doesn't work like this: self.update() rather it works like this: self.update. Why so? Is is some special way that command option of a button works? I think a method or a function should be called with those braces (), unless it's a property:
i.e.
#name.setter:
def setter(self, name):
self.name = name
#main
object.name = "New_obj"
Note: The above is just a template so you might get my point. I didn't write the complete valid code. Including class and everything.
from tkinter import *
class MuchMore(Frame):
def __init__(self, master):
super(MuchMore,self).__init__(master)
self.count =0
self.grid()
self.widgets()
def widgets(self):
self.bttn1 = Button(self, text = "OK")
self.bttn1.configure(text = "Total clicks: 0")
self.bttn1["command"] = self.update # This is what I am taking about
self.bttn1.grid()
def update(self):
self.count += 1
self.bttn1["text"] = "Total clicks" + str(self.count)
#main
root = Tk()
root.title("Much More")
root.geometry("324x454")
app = MuchMore(root)
It is a high order function, meaning you are referencing a function as an object. You are not calling the function and assigning the command to the return value of the function. See here for more information.
The command parameter takes a reference to a function -- ie: the name of the function. If you add parenthesis, you're asking python to execute the function and give the result of the function to the command parameter.

How to import a variable from another function and another class?

I'm trying but it's not working. I have the following code line:
class Run:
def Method(self, choice):
print "%sZip :\t%s%s\n".decode('utf-8') % (Basic_Green, White, choice.start().LoadJson['zip'])
And this is variable, and is within another class, and another function:
class Host_Method:
def start(self):
My_API = requests.get("http://ip-api.com/json/%s" % socket.gethostbyname(sys.argv[2]))
LoadJson = json.loads(My_API.content)
The error:
Traceback (most recent call last):
File "InfoIP.py", line 78, in <module>
elif sys.argv[1] == "-h": Run().Method(Host_Method())
File "/Pentest/InfoIP2/Libraries/InfoIP_Functions.py", line 159, in Method
print "%sZip :\t%s%s\n".decode('utf-8') % (Basic_Green, White, choice.LoadJson['zip'])
AttributeError: Host_Method instance has no attribute 'LoadJson'
You probably want them to be stored in an instance variable (self....). And you probably want your start to be an __init__ method. Your corrected class could look like:
class HostMethod:
def start(self):
self.my_API = requests.get("http://ip-api.com/json/{0}".format(socket.gethostbyname(sys.argv[2])))
self.load_json = json.loads(self.my_API.content)
Then, you could do:
class Run:
def Method(self, choice):
print "{0}Zip :\t{1}{2}\n".decode('utf-8').format(Basic_Green, White, choice.load_json['zip'])
a = Run()
a.method(HostMethod())
See also:
https://docs.python.org/3.4/tutorial/classes.html

why I can't update a variable value and return self.func(*args)?

I'm sending a variable value from programa1 for a new object using :
def send_price(self):
self.pricesend = float(self.text1.get()) #this take a value from a tkinker.Entry
print(self.pricesend)
objetoprograma1.Object(self.pricesend)
the object "objetoprograma1" return a new value using:
class Object():
def __init__(self, price):
self.price_recibe = float(price)
print(self.price_recibe)
self.new_price = self.price_recibe + 10
print(self.new_price)
programa1.Aplication.recibe_newprice(self, float(self.new_price))
now I want to update the value in the principal1 tkinter.Entry called self.text1:
def recibe_newprice(self, new_price):
self.new_price = new_price
print("price new recibe" , self.new_price)
## this don't work.. this don't update or change the value in the tkinter.Entry
self.text1.delete(0, len(self.text1.get()))
self.text1.insert(self.my_main, str(self.new_price))
I have the following exception:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1482, in __call__
return self.func(*args)
File "B:\MAESTRIA\PYTHON\trabajos\hello\programa1.py", line 38, in send_price
objetoprograma1.Object(self.pricesend)
File "B:\MAESTRIA\PYTHON\trabajos\hello\objetoprograma1.py", line 19, in __init__
programa1.Aplication.recibe_newprice(self, float(self.new_price))
File "B:\MAESTRIA\PYTHON\trabajos\hello\programa1.py", line 51, in recibe_newprice
self.text1.delete(self.my_main, len(self.text1.get()))
AttributeError: 'Object' object has no attribute 'text1'
the full programa1.py
# -*- coding: latin-1 -*-
import tkinter
import objetoprograma1
import time
class Aplication():
def __init__(self,my_main):
self.my_main = my_main
self.variables()
self.GUI()
def variables (self):
self.price = None
self.list = []
def GUI(self):
self.text1 = tkinter.Entry()
self.text1.insert(0, "1000")
self.text1.grid(column = 0, row = 0)
self.boton1 = tkinter.Button(self.my_main, text = "sendprice", command = self.send_price )
self.boton1.grid(column=1, row = 0)
def send_price(self):
self.pricesend = float(self.text1.get())
print(self.pricesend)
objetoprograma1.Object(self.pricesend)
def recibe_newprice(self, new_price):
self.new_price = new_price
print("price new recibe" , self.new_price)
## this don't work
self.text1.delete(0, len(self.text1.get()))
self.text1.insert(self.my_main, str(self.new_price))
if __name__ == "__main__":
root = tkinter.Tk()
#root.geometry("800x500+0+0")
root.title("titulo")
app = Aplication(my_main=root)
root.mainloop()
and objetoprograma1.py
# -*- coding: latin-1 -*-
import programa1
import tkinter
import time
class Object():
def __init__(self, price):
self.price_recibe = float(price)
print(self.price_recibe)
self.new_price = self.price_recibe + 10
print(self.new_price)
programa1.Aplication.recibe_newprice(self, float(self.new_price))
Look at your Object class and look at the exception message. You are calling the recibe_newprice method, but passing it the Object instance (Object has no text1 attribute). The recibe_newprice is written for the Aplication class and as such expects self to be an instance of the Aplication class. You seem to be mixing up what classes are for or how the self argument works.
My first tip is to name things with more descriptive names. Names like Object, Application, and Program1 don't tell the reader anything about what the purpose of those objects are.
Second, do you know the difference between classes and functions? Maybe this will help. I would code the send_price method this way:
def send_price(self, price_recibe):
pricesend = float(self.text1.get())
print(pricesend)
print(price_recibe)
new_price = price_recibe + 10
print(new_price)
self.recibe_newprice(new_price)
If this doesn't make sense why I'm doing things this way or why this might be considered better/easier than the way you did it then I suggest researching how python classes, attribute assignment, and argument passing works.

Categories

Resources