tkinter woes when porting 2.x code to 3.x, 'tkinter' module attribute doesn't exist
UPDATED: SEE BELOW
I've been porting the code for this assignment: htt开发者_StackOverflow社区p://www.stanford.edu/class/cs221/progAssignments/PA1/search.html (the entire source code is available as zip from there) from Python 2.x to 3.x. Note, porting is not the assignment, that's just me trying to keep the code up to date and avoiding installing another version of Python...
After the usual 2.x -> 3.x syntax fixes (printing, exception raising, etc), and realizing that the module Tkinter
is now known as tkinter
in 3.x (lower-case), I've run into stranger problems, with this snippet and several others like it:
def keys_pressed(d_o_e=tkinter.tkinter.dooneevent,d_w=tkinter.tkinter.DONT_WAIT)
The errors are of the type:
AttributeError: 'module' object has no attribute 'tkinter'
Code completion in my IDE and the variable trace indeed seems to indicate that the tkinter
module has no attribute or sub-class tkinter
under which one might refer to dooneevent
or DONT_WAIT
. However, there are a few other references on the Internet of people using constructs like
_tkinter.dooneevent(_tkinter.DONT_WAIT)
to move the main loop ahead, but even referencing it like that still yields the same error.
Any ideas greatly appreciated.
UPDATE: Referring to the _root_window via lambda notation seems to work, as in it no longer complains pre-execution time in the majority of cases. To my untrained eye however, this is basically "magic", and as such I have little idea what this subsequent error is saying or how to work around it. The method now looks like this, with my changes in the first line:
def move_to(object, x, y=None, d_o_e=lambda arg: _root_window(arg), d_w=tkinter._tkinter.DONT_WAIT):
if y is None:
try: x, y = x
except: raise 'incomprehensible coordinates'
horiz = True
newCoords = []
current_x, current_y = _canvas.coords(object)[0:2] # first point
for coord in _canvas.coords(object):
if horiz:
inc = x - current_x
else:
inc = y - current_y
horiz = not horiz
newCoords.append(coord + inc)
_canvas.coords(object, *newCoords)
d_o_e(d_w)
and the error I get is:
TypeError: 'Tk' object is not callable
referencing the line where the method is defined (first line above).
It appears Tkinter.tkinter
was changed to tkinter._tkinter
in Python 3. Compare these docs from Python 2 with these from Python 3. Also, dooneevent
is no longer in tkinter._tkinter
, but is still a member of the Tk
(aka root
) object.
So change your code to
def keys_pressed(d_o_e=lambda arg: _root_window.dooneevent(arg),
d_w=tkinter._tkinter.DONT_WAIT):
This takes advantage of the fact that in your linked code _root_window
is global
, so while _root_window
is not available when the class is defined, it will be available when the lambda is run.
精彩评论