如何将此示例从 python2 转换为 python3

Posted

技术标签:

【中文标题】如何将此示例从 python2 转换为 python3【英文标题】:How to convert this example from python2 to python3 【发布时间】:2018-05-30 18:08:58 【问题描述】:

我正在尝试将 github 中的一个工作示例从 python2 转换为 python3,但遇到了一个我不明白的问题。

原文是https://gist.github.com/EugeneBakin/76c8f9bcec5b390e45df 我应用以下补丁并收到有关 SampleApp init 方法的参数过多的错误消息。由于我不明白为什么当唯一的调用根本没有参数时,原始版本有它的 *args 和 **kwargs,所以对我来说没有什么意义。但它适用于 python2,所以我希望它也适用于 python3,因为我认为这种用法很有用。

但是,这可能无关紧要,因为错误消息上的堆栈跟踪不包括该调用或任何与此相关的调用。另一个谜题。

我想解决这个问题,而不是盲目地删除参数,因为当我在实际用例中应用它时可能需要一些参数。

我还想删除作为 * 的导入,因为我认为它很危险并且隐藏了对读者有用的信息。

补丁:

--- VSFrame.py  2017-12-16 14:30:33.458923856 -0800
+++ VSFrame3.py 2017-12-16 15:01:21.914423486 -0800
@@ -1,21 +1,21 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
-from Tkinter import *   # from x import * is bad practice
-from ttk import *
+import tkinter as tk
+import tkinter.ttk as ttk

 # http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame

-class VerticalScrolledFrame(Frame):
+class VerticalScrolledFrame(ttk.Frame):
     """A pure Tkinter scrollable frame that actually works!
     * Use the 'interior' attribute to place widgets inside the scrollable frame
     * Construct and pack/place/grid normally
     * This frame only allows vertical scrolling
     """
     def __init__(self, parent, *args, **kw):
-        Frame.__init__(self, parent, *args, **kw)            
+        super().__init__(self, parent, *args, **kw)            

         # create a canvas object and a vertical scrollbar for scrolling it
-        vscrollbar = Scrollbar(self, orient=VERTICAL)
+        vscrollbar = ttk.Scrollbar(self, orient=VERTICAL)
         vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
         canvas = Canvas(self, bd=0, highlightthickness=0,
                         yscrollcommand=vscrollbar.set)
@@ -51,9 +51,9 @@

 if __name__ == "__main__":

-    class SampleApp(Tk):
+    class SampleApp(tk):
         def __init__(self, *args, **kwargs):
-            root = Tk.__init__(self, *args, **kwargs)
+            root = tk.__init__(self, *args, **kwargs)


             self.frame = VerticalScrolledFrame(root)

在威廉的评论之后(谢谢),现在是

--- VSFrame.py  2017-12-16 14:30:33.458923856 -0800
+++ VSFrame3.py 2017-12-16 16:04:00.938380716 -0800
@@ -1,21 +1,21 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
-from Tkinter import *   # from x import * is bad practice
-from ttk import *
+import tkinter as tk
+import tkinter.ttk as ttk

 # http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame

-class VerticalScrolledFrame(Frame):
+class VerticalScrolledFrame(ttk.Frame):
     """A pure Tkinter scrollable frame that actually works!
     * Use the 'interior' attribute to place widgets inside the scrollable frame
     * Construct and pack/place/grid normally
     * This frame only allows vertical scrolling
     """
     def __init__(self, parent, *args, **kw):
-        Frame.__init__(self, parent, *args, **kw)            
+        super().__init__(self, parent, *args, **kw)            

         # create a canvas object and a vertical scrollbar for scrolling it
-        vscrollbar = Scrollbar(self, orient=VERTICAL)
+        vscrollbar = ttk.Scrollbar(self, orient=VERTICAL)
         vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
         canvas = Canvas(self, bd=0, highlightthickness=0,
                         yscrollcommand=vscrollbar.set)
@@ -51,10 +51,9 @@

 if __name__ == "__main__":

-    class SampleApp(Tk):
+    class SampleApp(tk.Tk):
         def __init__(self, *args, **kwargs):
-            root = Tk.__init__(self, *args, **kwargs)
-
+            root = tk.TK.__init__(self, *args, **kwargs)

             self.frame = VerticalScrolledFrame(root)
             self.frame.pack()

【问题讨论】:

应该是+ class SampleApp(tk.Tk): @Willem 这让我更进一步,但谢谢。现在它抱怨 module.__init__() 的第一个参数必须是 str,而不是 SampleApp。 用 Python3 安装了程序2to3,它可以将许多元素从 Python 2 转换为 Python 3。 【参考方案1】:

我让它更接近https://docs.python.org/3.5/library/tkinter.html#a-simple-hello-world-program 中的风格,让它工作起来

完整来源如下。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import tkinter as tk
import tkinter.ttk as ttk

# Python3 version of http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame

class VerticalScrolledFrame(ttk.Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows vertical scrolling
    """
    def __init__(self, parent):
        super().__init__(parent)

        # create a canvas object and a vertical scrollbar for scrolling it
        vscrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL)
        vscrollbar.pack(fill=tk.Y, side=tk.RIGHT, expand=tk.FALSE)
        canvas = tk.Canvas(self, bd=0, highlightthickness=0,
                        yscrollcommand=vscrollbar.set)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.TRUE)
        vscrollbar.config(command=canvas.yview)

        # reset the view
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = ttk.Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior,
                                           anchor=tk.NW)

        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the canvas's width to fit the inner frame
                canvas.config(width=interior.winfo_reqwidth())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the inner frame's width to fill the canvas
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)


if __name__ == "__main__":

    class SampleApp(ttk.Frame):
        def __init__(self, master=None):
            super().__init__(master)
            self.create_widgets()

        def create_widgets(self):
            self.frame = VerticalScrolledFrame(root)
            self.frame.pack()
            self.label = ttk.Label(text="Shrink the window to activate the scrollbar.")
            self.label.pack()
            buttons = []
            for i in range(10):
                buttons.append(ttk.Button(self.frame.interior, text="Button " + str(i)))
                buttons[-1].pack()

    root = tk.Tk()
    app = SampleApp(master=root)
    app.mainloop()

【讨论】:

以上是关于如何将此示例从 python2 转换为 python3的主要内容,如果未能解决你的问题,请参考以下文章

如何将此代码从 Dijkstra 转换为 Astar?

如何将此查询从 MSSQL 转换为 MySQL?

如何将此功能从 Excel 转换为 Open Office?

如何将此代码从 oracle 转换为 redshift?

如何以编程方式确定用户是不是从 iOS 中的 Adwords 转换而来,或者是不是可以将此数据转换为用户属性?

如何将此 SetLike 集合从 Scala 2.12 转换为 2.13?