将2.x代码移植到3.x时,tkinter出现问题,'tkinter'模块属性不存在 [英] tkinter woes when porting 2.x code to 3.x, 'tkinter' module attribute doesn't exist

查看:283
本文介绍了将2.x代码移植到3.x时,tkinter出现问题,'tkinter'模块属性不存在的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在移植此作业的代码: http://www.stanford.edu/class/cs221/progAssignments/PA1/search.html (完整的源代码可从此处以zip格式获得) 从Python 2.x到3.x.请注意,移植不是任务,这只是我在尝试使代码保持最新状态,并避免安装其他版本的Python ...

I've been porting the code for this assignment: http://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...

在修复了常见的2.x-> 3.x语法(打印,引发异常等)之后,意识到模块Tkinter现在在3.x中被称为tkinter(小写),这个代码段和其他一些类似代码让我遇到了陌生的问题:

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)

错误属于以下类型:

AttributeError: 'module' object has no attribute 'tkinter'

我的IDE中的代码完成和变量跟踪的确似乎表明tkinter模块没有属性或子类tkinter,在该属性或子类中可能会引用dooneeventDONT_WAIT.但是,在人们的互联网上,还有其他一些引用,例如使用

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.

任何想法都很感激.

更新:通过lambda表示法引用_root_window似乎有效,因为在大多数情况下,它不再抱怨预执行时间.但是,对我未经训练的人来说,这基本上是魔术",因此我不知道随后出现的错误在说什么或如何解决.该方法现在看起来像这样,我在第一行中做了更改:

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)

我得到的错误是:

TypeError: 'Tk' object is not callable              

引用定义方法的行(上面的第一行).

referencing the line where the method is defined (first line above).

推荐答案

在Python 3中,Tkinter.tkinter似乎已更改为tkinter._tkinter.比较

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.

因此将您的代码更改为

def keys_pressed(d_o_e=lambda arg: _root_window.dooneevent(arg),
        d_w=tkinter._tkinter.DONT_WAIT):

这利用了以下事实:链接的代码_root_windowglobal,因此虽然在定义类时_root_window不可用,但在运行lambda时将可用.

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.

这篇关于将2.x代码移植到3.x时,tkinter出现问题,'tkinter'模块属性不存在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆