Creating multiple variables / strings within loops in Python - python

I'm trying to create a program that, well, looks something like this:
self.b1 = Checkbutton(self, variable=self.b1v, text="1.")
self.b1.grid()
self.b2v = IntVar()
self.b2 = Checkbutton(self, variable=self.b2v, text="2.")
self.b2.grid()
self.b3v = IntVar()
self.b3 = Checkbutton(self, variable=self.b3v, text="3.")
self.b3.grid()
self.b4v = IntVar()
Well, kinda like that, just... 30+ times. There has GOT to be a better way to do this. However, I have no idea how to do this in a loop. I imagine it would look something like this:
while i <= 32:
n = "self.b" + str(i) + "v = IntVar() \n"
n += "self.b" + str(i) + " = Checkbutton(self, variable=self.b" + str(i) + "v) \n"
n += "self.b" + str(i) + ".grid()\n"
exec(n)
...Or something like that... But that throws an error:
Traceback (most recent call last):
File "/Users/jonahswersey/Documents/toggle flags.py", line 126, in <module>
app = Application()
File "/Users/jonahswersey/Documents/toggle flags.py", line 93, in __init__
self.createWidgets()
File "/Users/jonahswersey/Documents/toggle flags.py", line 117, in createWidgets
exec(m)
File "<string>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk/Tkinter.py", line 2337, in __init__
Widget.__init__(self, master, 'checkbutton', cnf, kw)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk/Tkinter.py", line 1923, in __init__
BaseWidget._setup(self, master, cnf)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk/Tkinter.py", line 1903, in _setup
if cnf.has_key('name'):
AttributeError: IntVar instance has no attribute 'has_key'
...whereas just manually entering them doesn't. Anyone have any advice for me?

Something like this?
num_buttons = 3
self.b_vars = [IntVar() for i in range(num_buttons)]
self.b = [CheckButton(self, variable=self.b_vars[i], text="%d." % (i + 1)) for i in range(num_buttons)]
for button in self.b:
button.grid()

You're looking for setattr().

Related

TypeError: cannot pickle 'weakref' object

Quite new to multiprocessing here. I have a code that runs two processes. One to continuously receive data blocks from the server and put it inside a queue and the other to remove the data blocks from the queue and process it.
Below is my client code:
import socket
import turtle
import multiprocessing
from multiprocessing import Process, Queue
from tkinter import *
class GUI:
def __init__(self, master):
rec_data = recv_data()
self.master = master
master.title("Collision Detection")
self.input_label = Label(root, text="Input all the gratings set straight wavelength values in nm")
self.input_label.grid(row=0)
self.core_string = "Core "
self.entries = []
self.label_col_inc = 0
self.entry_col_inc = 1
self.core_range = range(1, 5)
for y in self.core_range:
self.core_text = self.core_string + str(y) + '_' + '25'
self.core_label = Label(root, text=self.core_text)
self.entry = Entry(root)
self.core_label.grid(row=1, column=self.label_col_inc, sticky=E)
self.entry.grid(row=1, column=self.entry_col_inc)
self.entries.append(self.entry)
self.label_col_inc += 2
self.entry_col_inc += 2
self.threshold_label = Label(root, text="Threshold in nm")
self.entry_threshold = Entry(root)
self.threshold_label.grid(row=2, sticky=E)
self.entry_threshold.grid(row=2, column=1)
self.light_label = Label(root, text='Status')
self.light_label.grid(row=3, column=3)
self.canvas = Canvas(root, width=150, height=50)
self.canvas.grid(row=4, column=3)
# Green light
self.green_light = turtle.RawTurtle(self.canvas)
self.green_light.shape('circle')
self.green_light.color('grey')
self.green_light.penup()
self.green_light.goto(0, 0)
# Red light
self.red_light = turtle.RawTurtle(self.canvas)
self.red_light.shape('circle')
self.red_light.color('grey')
self.red_light.penup()
self.red_light.goto(40, 0)
self.data_button = Button(root, text="Get data above threshold", command=rec_data.getData)
self.data_button.grid(row=5, column=0)
class recv_data:
def __init__(self):
self.buff_data = multiprocessing.Queue()
self.p1 = multiprocessing.Process(target=self.recvData)
self.p2 = multiprocessing.Process(target=self.calculate_threshold)
self.host = '127.0.0.1'
self.port = 5001
self.s = socket.socket()
self.s.connect((self.host, self.port))
# function to receive TCP data blocks
def getData(self):
len_message = self.s.recv(4)
bytes_length = int(len_message.decode('utf-8')) # for the self-made server
recvd_data = self.s.recv(bytes_length)
self.buff_data.put(recvd_data)
self.p1.start()
self.p2.start()
self.p1.join()
self.p2.join()
def recvData(self):
len_message = self.s.recv(4)
while len_message:
bytes_length = int(len_message.decode('utf-8')) # for the self-made server
recvd_data = self.s.recv(bytes_length)
self.buff_data.put(recvd_data)
len_message = self.s.recv(4)
else:
print('out of loop')
self.s.close()
def calculate_threshold(self):
rmv_data = self.buff_data.get()
stringdata = rmv_data.decode('utf-8')
rep_str = stringdata.replace(",", ".")
splitstr = rep_str.split()
# received wavelength values
inc = 34
wav_threshold = []
for y in gui.entries:
straight_wav = float(y.get())
wav = float(splitstr[inc])
wav_diff = wav - straight_wav
if wav_diff < 0:
wav_diff = wav_diff * (-1)
wav_threshold.append(wav_diff)
inc += 56
threshold = float(gui.entry_threshold.get())
for x in wav_threshold:
if (x > threshold):
gui.red_light.color('red')
gui.green_light.color('grey')
else:
gui.red_light.color('grey')
gui.green_light.color('green')
# function to write into the file
def write_file(self, data):
with open("Output.txt", "a") as text_file:
text_file.write('\t'.join(data[0:]))
text_file.write('\n')
if __name__ == '__main__':
root = Tk()
gui1 = GUI(root)
root.mainloop()
The error I get is shown below:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "C:/Users/PycharmProjects/GUI/GUI_multiprocess.py", line 85, in getData
self.p2.start()
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\context.py", line 224, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\context.py", line 326, in _Popen
return Popen(process_obj)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
reduction.dump(process_obj, to_child)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle 'weakref' object
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\spawn.py", line 126, in _main
self = reduction.pickle.load(from_parent)
EOFError: Ran out of input
What am I doing wrong here and how can I fix it? Any help is appreciated. Thank you!
I just came to the same traceback and managed to solve it. It was due to that an object had a running or exited Process as a variable and it was starting another Process using that object.
Problem
This is a minimal code to produce your error:
import multiprocessing
class Foo:
def __init__(self):
self.process_1 = multiprocessing.Process(target=self.do_stuff1)
self.process_2 = multiprocessing.Process(target=self.do_stuff2)
def do_multiprocessing(self):
self.process_1.start()
self.process_2.start()
def do_stuff1(self):
print("Doing 1")
def do_stuff2(self):
print("Doing 2")
if __name__ == '__main__':
foo = Foo()
foo.do_multiprocessing()
[out]:
Traceback (most recent call last):
File "myfile.py", line 21, in <module>
foo.do_multiprocessing()
File "myfile.py", line 11, in do_multiprocessing
self.process_2.start()
File "...\lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
File "...\lib\multiprocessing\context.py", line 224, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "...\lib\multiprocessing\context.py", line 327, in _Popen
return Popen(process_obj)
File "...\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
reduction.dump(process_obj, to_child)
File "...\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle 'weakref' object
Doing 1
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "...\lib\multiprocessing\spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "...\lib\multiprocessing\spawn.py", line 126, in _main
self = reduction.pickle.load(from_parent)
EOFError: Ran out of input
So the issue is that Foo contains also the running/exited process foo.process_1 when it starts foo.process_2.
Solution 1
Set foo.process_1 to None or something else. Or store the Processes somewhere else than in foo to prevent being passed when starting process_2.
...
def do_multiprocessing(self):
self.process_1.start()
self.process_1 = None # Remove exited process
self.process_2.start()
...
Solution 2
Remove the problematic variable (process_1) from pickling:
class Foo:
def __getstate__(self):
# capture what is normally pickled
state = self.__dict__.copy()
# remove unpicklable/problematic variables
state['process_1'] = None
return state
...
This seems to be problem in newer Python versions. My own code worked fine for 3.7 but failed due to this issue in 3.9.
I tested your code (from recv_data). Since you join the processes and need them, you should do the solution 2 or store the processes somewhere else than in recv_data. Not sure what other problems your code has.

No idea what's causing this error "AttributeError: '_io.TextIOWrapper' object has no attribute 'tk'"

The code keeps throwing the AttributeError: '_io.TextIOWrapper' object has no attribute 'tk' and I can't figure out what's causing it, I looked at other posts and nothing has helped me to get an idea of what's going on.
Below is the code that's causing it.
def showhwk(lesson, popup):
lesson = lesson.replace("/","")
popup.withdraw()
show = Tk()
show.title("Homework marks for "+lesson)
show.geometry("+{}+{}".format(positionRight, positionDown))
try:
with open(lesson+".csv", "r") as show:
csvlist = list(csv.reader(show))
for label in range (len(csvlist)):
Label(show, text = "hello").grid(row = label)
except FileNotFoundError:
show.title("Error!")
error = Label(show, text = "Homework file was not found")
error.grid(row = 0)
def goback3(show):
popup.deiconify()
show.withdraw()
returnbut = Button(show, text = "Return", bg = "#79838e", command = lambda: goback3(show)).grid(row = 40, sticky = W+E)
This is the full error:
Traceback (most recent call last):
File "C:\Users\Olek\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "D:\Desktop\Folders\Python\Coursework\coursework code main.py", line 242, in <lambda>
show = Button(popup, text = "Show homework marks", bg = "green", command = lambda: showhwk(lesson, popup))
File "D:\Desktop\Folders\Python\Coursework\coursework code main.py", line 278, in showhwk
Label(show, text = "hello").grid(row = label)
File "C:\Users\Olek\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 3143, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Users\Olek\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 2561, in __init__
BaseWidget._setup(self, master, cnf)
File "C:\Users\Olek\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 2530, in _setup
self.tk = master.tk
AttributeError: '_io.TextIOWrapper' object has no attribute 'tk'
You first define show like this:
show = Tk()
Later, you redefine show to be an open file handle with this statement:
with open(lesson+".csv", "r") as show:
Then, you try to use show as the master for a widget here:
Label(show, text = "hello").grid(row = label)
Because show is no longer a widget, it can't be used as the master for another widget. And that is why you get a tkinter error.

Getting a strange _tkinter.TclError: unknown option

I have made a small game where you progress through your life much like instlife but made in python with Tkinter. It is not complete and no where near being completed as i always get this same error.
This is my code
import tkinter
window = tkinter.Tk()
window.geometry("275x400")
window.title("Life")
year = 1980
age = 0
def ageButton():
global year
global age
year += 1
age += 1
yearText.configure(text=year)
dynamicText.configure("You are %d" %age)
yearText = tkinter.Label(window, text=year, anchor="n", width="270")
dynamicText = tkinter.Label(window, text="You are %d" %age, anchor="n",
width="270", height="495")
ageButton = tkinter.Button(window, text="Age", width="270",
command=ageButton)
ageButton.pack()
yearText.pack()
dynamicText.pack()
window.mainloop()
this is the error i get
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Ed\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1702, in __call__
return self.func(*args)
File "C:\Users\Ed\Desktop\Lifee2\Life2.py", line 16, in ageButton
dynamicText.configure("You are %d" %age)
File "C:\Users\Ed\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1482, in configure
return self._configure('configure', cnf, kw)
File "C:\Users\Ed\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1472, in _configure
return self._getconfigure1(_flatten((self._w, cmd, '-'+cnf)))
File "C:\Users\Ed\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1460, in _getconfigure1
x = self.tk.splitlist(self.tk.call(*args))
_tkinter.TclError: unknown option "-You are 1"
When you call the configure method, you must tell tkinter what value you are changing. In your case you need to change this:
dynamicText.configure("You are %d" %age)
... to this:
dynamicText.configure(text="You are %d" %age)

'File not found' while importing gif for Tkinter.Label

I'm trying to import gif into a Tkinter.Label. I'm getting a file does not exist error. I have double checked the path and file name.
Below is the error message I get.
Traceback (most recent call last):
File "C:\Users\sachin\Desktop\Project California.py", line 39, in <module>
if __name__=='__main__': main()
File "C:\Users\sachin\Desktop\Project California.py", line 35, in main
feedback = Feedback(root)
File "C:\Users\sachin\Desktop\Project California.py", line 11, in __init__
self.logo = PhotoImage(file= "‪C:\\Users\\sachin\\Desktop\\signature.gif")
File "C:\Users\sachin\AppData\Local\Programs\Python\Python36
\lib\tkinter\__init__.py", line 3542, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't open "‪C:\Users\sachin\Desktop\signature.gif": no
such file or directory
Here is the code I used.
def __init__(self,master):
self.frame_header = ttk.Frame(master)
self.logo = PhotoImage(file= "‪C:\\Users\\sachin\\Desktop\\signature.gif")
ttk.Label(self.frame_header, image = self.logo)
I'm a noob in python programming. Apologies if the questions is too trivial.
I get the same error and I'm sure the path is right as well. In fact, it seems to find the file every other time it tries, with very similar code.
for r in range(0,5):
for c in range(1,4):
fn = file_name(c)
try:
photo = tk.PhotoImage(fn)
tk.Button(C, image = photo, width = "16", height = "16").grid(row = r,column = c)
except Exception as exception:

Updating Python tkinter label in realtime

I want to update my label in python after the loop has started.
Sadly I get the error
File "mygui.py", line 19, in <module>
GUI.user_said("General Kenobi")
File "mygui.py", line 16, in user_said
self.my_label['text'] = self.label_text
File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1486, in __setitem__
self.configure({key: value})
File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1479, in configure
return self._configure('configure', cnf, kw)
File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1470, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: invalid command name ".!label"
which doesn't help me at all...
My Code:
from tkinter import *
class MyGUI:
"""A simple class"""
def __init__(self):
self.__main_window = Tk()
self.label_text = "Hello There"
self.my_label = Label(self.__main_window, text=self.label_text)
self.my_label.pack()
self.__main_window.mainloop()
def user_said(self, users_request):
"""Returns what the user says"""
self.label_text = "You said:\n{}\n\n".format(users_request)
self.my_label.config(text=self.label_text)
GUI = MyGUI()
GUI.user_said("General Kenobi")
I'm very glad if someone helps me to find a solution for my problem.
Because MyGUI.__init__ calls self.__main_window.mainloop(), it will not return until the main window is destroyed. Therefore, by the time you call GUI.user_said("General Kenobi"), none of the widgets exist any more.

Categories

Resources