I know the codes not the best well written but the only problem I'm having(besides the interpreting of the macro commands, the one here is just a base for me to work on) is how the UpdateLabels.start() method returns:

Traceback (most recent call last):
  File "C:\Users\Erik\Desktop\Stuff from last Night\MouseMacro.py", line 77, in <module>
    main()
  File "C:\Users\Erik\Desktop\Stuff from last Night\MouseMacro.py", line 75, in main
    UpdateLabels().start()
  File "C:\Python30\lib\threading.py", line 446, in start
    if not self._initialized:
AttributeError: 'UpdateLabels' object has no attribute '_initialized'

This is my code:

#Python 3k
from tkinter import *
from threading import Thread

import mouse#Third Party found at http://www.python-forum.org/pythonforum/viewtopic.php?f=2&t=8976

XPOS = 0
YPOS = 0

class UpdateLabels(Thread):#activates in main...did not work?
    def __init__(self):
        global XPOS
        global YPOS
    def _initialize(self):
        run()
    def run(self):
        XPOS = mouse.getpos()[0]
        YPOS = mouse.getpos()[1]
def Help():
    messagebox._show(title="Help", message="Do This...")#add help message

def Load_Macro():#Add Lots of Error Checking here!!!!!!!!!!!!!(Make sure file exitsts!)
    f = open(filedialog.askopenfilename(), 'r')
    data = f.read()
    f.close()
    txt_Macro.delete(1.0, END)
    txt_Macro.insert(END, data)


def Interpret(text):#NEED TO FIX
    text = text.split(';')
    for i in text:
        com = i.split()
        if com[0] == 'MOV':
            #parse for move command
            b = com.split()
            mouse.move(int(b[0]), int(b[1]))
        elif com[0] == 'CLK':
            mouse.click()
        elif com[0] == 'SLD':
            #parse for where to move and speed 'slow' or 'fast'
            b = com.split()
            mouse.slide(int(b[0]), int(b[1]), b[2])
        elif com[0] == 'HOLD':
            mouse.hold()
        elif com[0] == 'RCLK':
            mouse.rightclick()
        elif com[0] == 'RHOLD':
            mouse.righthold()
        else:
            return False#returns an ERROR if messup
def start_macro():
    Interpret(txt_Macro.get(1.0, END))
    print(txt_Macro.get(1.0, END))

root = Tk()

#Use these to update mouse positions
lbl_mouse_xpos = Label(root, text="Mouse X Pos: "+str(XPOS))
lbl_mouse_ypos = Label(root, text="Mouse Y Pos: "+str(YPOS))

txt_Macro = Text(root, height=1)#Use this to get macro text

cmd_start_macro = Button(root, text="Start", command=start_macro)
cmd_help = Button(root, text="Help", command=Help)
cmd_load_macro = Button(root, text="Load Macro", command=Load_Macro)

def main():
    lbl_mouse_xpos.pack()
    lbl_mouse_ypos.pack()
    txt_Macro.pack()
    cmd_start_macro.pack()
    cmd_help.pack()
    cmd_load_macro.pack()
    UpdateLabels().start()
    root.mainloop()
main()

Any help with the error message and the threading module would be greatly apreciated.

Dani AI

Generated

The traceback means the Thread base-class never finished initialising. As noted, a Thread subclass must call the base constructor so Thread.start() can find the internal flags (like _initialized). 's alternative of subclassing threading.Thread is equivalent — the important bit is invoking the thread base init.

Two practical options are safest:

  1. Avoid a background thread for UI updates and poll the mouse from the GUI thread with after() (recommended for tkinter). This keeps all label updates in the main thread and prevents subtle crashes.
def poll_mouse():
    x, y = mouse.getpos()
    lbl_mouse_xpos.config(text="Mouse X Pos: {}".format(x))
    lbl_mouse_ypos.config(text="Mouse Y Pos: {}".format(y))
    root.after(100, poll_mouse)

poll_mouse()
root.mainloop()
  1. If you must use a worker thread, call the base constructor (use super().__init__() in Python 3), mark the thread daemon if desired, and never call tkinter methods from that thread. Push position tuples to a queue.Queue from the worker and consume the queue in the GUI thread via after().

Also fix these common bugs seen in the original code:

  • Calling Thread.__init__() (or super().__init__()) is mandatory when overriding __init__.
  • Assigning to globals in run() requires a global statement; better: use instance attributes or a queue.
  • Parsing functions should operate on token strings returned by split() — avoid calling split() on a list.
  • Use the public tkinter helpers (for example, tkinter.messagebox.showinfo) rather than private internals.

Checklist: call the base thread initializer, keep GUI work in the main thread, use after() or queue+polling, and fix scope/parse bugs.

Recommended Answers

All 2 Replies

I quote the python 3.0 documentation: "If the subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread." So I think you should start your class like this

class UpdateLabels(Thread):#activates in main...did not work?
    def __init__(self):
        Thread.__init__(self)
        global XPOS
        global YPOS

Also, I don't understand your method _initialize . I don't think you need it.

Using
class UpdateLabels(threading.Thread):
should work too.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.