首页 > 解决方案 > tkinter GUI中str和int之间的Python TypeError,但不是CLI

问题描述

我正在为压缩和提取 YAZ0/SZS 文件的 CLI 应用程序创建 GUI,当我尝试通过 GUI 压缩时,我得到了这个。

TypeError:“str”和“int”的实例之间不支持“<”

但是当我通过终端执行 main.py 时,.\main.py -little -compress 3 -o compressed_dir.szs common/它工作正常。因此,基于此,我假设这TypeError是由于 GUI.py 而发生的,但我无法弄清楚是什么原因造成的。

我相信从 main.py 执行 pack 函数时,GUI_pack 函数中会发生错误。

GUI_pack 函数

def GUI_pack(src, out, endianness, compr_lvl):
    try:
        src = Path(src).resolve()
    except FileNotFoundError:
        messagebox.showerror("File Not Found", "The directory at " + src + " does not exist.")
        return

    try:
        out = Path(out).resolve()
    except FileNotFoundError:
        messagebox.showerror("File Not Found", "The file at " + out + " does not exist.")
        return

    src = os.path.abspath(src)
    pack(src, endianness, compr_lvl, out)
    messagebox.showinfo("Finsihed", "Packing Complete\nSource: " + str(src) + "\nOutput: " + str(out))

main.py 打包函数

def pack(root, endianness, level, outname):
    """
    Pack the files and folders in the root folder.
    """

    if "\\" in root:
        root = "/".join(root.split("\\"))

    if root[-1] == "/":
        root = root[:-1]

    arc = SarcLib.SARC_Archive(endianness=endianness)
    lenroot = len(root.split("/"))

    for path, dirs, files in os.walk(root):
        if "\\" in path:
            path = "/".join(path.split("\\"))

        lenpath = len(path.split("/"))

        if lenpath == lenroot:
            path = ""

        else:
            path = "/".join(path.split("/")[lenroot - lenpath:])

        for file in files:
            if path:
                filename = ''.join([path, "/", file])

            else:
                filename = file

            print(filename)

            fullname = ''.join([root, "/", filename])

            i = 0
            for folder in filename.split("/")[:-1]:
                if not i:
                    exec("folder%i = SarcLib.Folder(folder + '/'); arc.addFolder(folder%i)".replace('%i', str(i)))

                else:
                    exec("folder%i = SarcLib.Folder(folder + '/'); folder%m.addFolder(folder%i)".replace('%i', str(i)).replace('%m', str(i - 1)))

                i += 1

            with open(fullname, "rb") as f:
                inb = f.read()

            hasFilename = True
            if file[:5] == "hash_":
                hasFilename = False

            if not i:
                arc.addFile(SarcLib.File(file, inb, hasFilename))

            else:
                exec("folder%m.addFile(SarcLib.File(file, inb, hasFilename))".replace('%m', str(i - 1)))

    data, maxAlignment = arc.save()

    if level != -1:
        outData = libyaz0.compress(data, maxAlignment, level)
        del data

        if not outname:
            outname = ''.join([root, ".szs"])

    else:
        outData = data
        if not outname:
            outname = ''.join([root, ".sarc"])

    with open(outname, "wb+") as output:
        output.write(outData)

主文件

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# SARC Tool
# Version v0.4
# Copyright © 2017-2018 MasterVermilli0n / AboodXD

# This is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

################################################################
################################################################

import os
import sys
import time

try:
    import SarcLib

except ImportError:
    print("SarcLib is not installed!")
    ans = input("Do you want to install it now? (y/n)\t")
    if ans.lower() == 'y':
        import pip
        pip.main(['install', 'SarcLib==0.2'])
        del pip

        import SarcLib

    else:
        sys.exit(1)

try:
    import libyaz0

except ImportError:
    print("libyaz0 is not installed!")
    ans = input("Do you want to install it now? (y/n)\t")
    if ans.lower() == 'y':
        import pip
        pip.main(['install', 'libyaz0==0.5'])
        del pip

        import libyaz0

    else:
        sys.exit(1)


def extract(file):
    """
    Extrct the given archive
    """
    with open(file, "rb") as inf:
        inb = inf.read()

    while libyaz0.IsYazCompressed(inb):
        inb = libyaz0.decompress(inb)

    name = os.path.splitext(file)[0]
    ext = SarcLib.guessFileExt(inb)

    if ext != ".sarc":
        with open(''.join([name, ext]), "wb") as out:
            out.write(inb)

    else:
        arc = SarcLib.SARC_Archive()
        arc.load(inb)

        root = os.path.join(os.path.dirname(file), name)
        if not os.path.isdir(root):
            os.mkdir(root)

        files = []

        def getAbsPath(folder, path):
            nonlocal root
            nonlocal files

            for checkObj in folder.contents:
                if isinstance(checkObj, SarcLib.File):
                    files.append(["/".join([path, checkObj.name]), checkObj.data])

                else:
                    path_ = os.path.join(root, "/".join([path, checkObj.name]))
                    if not os.path.isdir(path_):
                        os.mkdir(path_)

                    getAbsPath(checkObj, "/".join([path, checkObj.name]))

        for checkObj in arc.contents:
            if isinstance(checkObj, SarcLib.File):
                files.append([checkObj.name, checkObj.data])

            else:
                path = os.path.join(root, checkObj.name)
                if not os.path.isdir(path):
                    os.mkdir(path)

                getAbsPath(checkObj, checkObj.name)

        for file, fileData in files:
            print(file)
            with open(os.path.join(root, file), "wb") as out:
                out.write(fileData)


def pack(root, endianness, level, outname):
    """
    Pack the files and folders in the root folder.
    """

    if "\\" in root:
        root = "/".join(root.split("\\"))

    if root[-1] == "/":
        root = root[:-1]

    arc = SarcLib.SARC_Archive(endianness=endianness)
    lenroot = len(root.split("/"))

    for path, dirs, files in os.walk(root):
        if "\\" in path:
            path = "/".join(path.split("\\"))

        lenpath = len(path.split("/"))

        if lenpath == lenroot:
            path = ""

        else:
            path = "/".join(path.split("/")[lenroot - lenpath:])

        for file in files:
            if path:
                filename = ''.join([path, "/", file])

            else:
                filename = file

            print(filename)

            fullname = ''.join([root, "/", filename])

            i = 0
            for folder in filename.split("/")[:-1]:
                if not i:
                    exec("folder%i = SarcLib.Folder(folder + '/'); arc.addFolder(folder%i)".replace('%i', str(i)))

                else:
                    exec("folder%i = SarcLib.Folder(folder + '/'); folder%m.addFolder(folder%i)".replace('%i', str(i)).replace('%m', str(i - 1)))

                i += 1

            with open(fullname, "rb") as f:
                inb = f.read()

            hasFilename = True
            if file[:5] == "hash_":
                hasFilename = False

            if not i:
                arc.addFile(SarcLib.File(file, inb, hasFilename))

            else:
                exec("folder%m.addFile(SarcLib.File(file, inb, hasFilename))".replace('%m', str(i - 1)))

    data, maxAlignment = arc.save()

    if level != -1:
        outData = libyaz0.compress(data, maxAlignment, level)
        del data

        if not outname:
            outname = ''.join([root, ".szs"])

    else:
        outData = data
        if not outname:
            outname = ''.join([root, ".sarc"])

    with open(outname, "wb+") as output:
        output.write(outData)


def printInfo():
    print("Usage:")
    print("  main [option...] file/folder")
    print("\nPacking Options:")
    print(" -o <output>           output file name (Optional)")
    print(" -little               output will be in little endian if this is used")
    print(" -compress <level>     Yaz0 (SZS) compress the output with the specified level(0-9) (1 is the default)")
    print("                       0: No compression (Fastest)")
    print("                       9: Best compression (Slowest)")
    print("\nExiting in 5 seconds...")
    time.sleep(5)
    sys.exit(1)


def main():
    print("SARC Tool v0.4")
    print("(C) 2017-2018 MasterVermilli0n / AboodXD\n")

    if len(sys.argv) < 2:
        printInfo()

    root = os.path.abspath(sys.argv[-1])
    if os.path.isfile(root):
        extract(root)

    elif os.path.isdir(root):
        endianness = '>'
        level = -1

        if "-little" in sys.argv:
            endianness = '<'

        if "-compress" in sys.argv:
            try:
                level = int(sys.argv[sys.argv.index("-compress") + 1], 0)

            except ValueError:
                level = 1

            if not 0 <= level <= 9:
                print("Invalid compression level!\n")
                print("Exiting in 5 seconds...")
                time.sleep(5)
                sys.exit(1)

        if "-o" in sys.argv:
            outname = sys.argv[sys.argv.index("-o") + 1]

        else:
            outname = ""

        pack(root, endianness, level, outname)

    else:
        print("File/Folder doesn't exist!")
        print("\nExiting in 5 seconds...")
        time.sleep(5)
        sys.exit(1)

if __name__ == '__main__': main()

图形用户界面.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# SARC Tool
# Version v0.4
# Copyright © 2017-2018 MasterVermilli0n / AboodXD

# GUI.py
# Author: Gigaboy-01 / Adam Oates
# Since: 5-15-2019

# This is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

################################################################
################################################################


from main import extract
from main import pack

import platform
import sys
import time
import os
import shutil
from pathlib import Path

import tkinter as Tk
import tkinter.ttk as Ttk
from tkinter import filedialog
from tkinter import messagebox

# opens file dialog and sets an Tk.Entry object text to file source
def selFile(entryfield):
    src = Tk.filedialog.askopenfilename(filetypes=[("SZS, SARC", "*.szs *.sarc")])
    if src != None:
        entryfield.delete(0, Tk.END)
        entryfield.insert(0, src)


def saveFile(entryfield):
    src = Tk.filedialog.asksaveasfilename(filetypes=[("SZS", "*.szs"),("SARC", "*.sarc")])
    if src != None:
        entryfield.delete(0, Tk.END)
        entryfield.insert(0, src)


def selDir(entryfield):
    src = Tk.filedialog.askdirectory()
    if src != None:
        entryfield.delete(0, Tk.END)
        entryfield.insert(0, src)


# centers window on screen with X and Y offset
def center(win, offx=0, offy=0):
    win.update_idletasks()
    width = win.winfo_width()
    height = win.winfo_height()
    x = (win.winfo_screenwidth() // 2) - (width // 2)
    y = (win.winfo_screenheight() // 2) - (height // 2)
    win.geometry('{}x{}+{}+{}'.format(width, height, (x+offx), (y+offy)))


def GUI_extract(src, out):
    try:
        src = Path(src).resolve()
    except FileNotFoundError:
        messagebox.showerror("File Not Found", "The file at " + src + " does not exist.")
        return

    try:
        out = Path(out).resolve()
    except FileNotFoundError:
        messagebox.showerror("File Not Found", "The directory at " + out + " does not exist.")
        return

    extract(src)

    # if output directory is same directory as source, then we don't need to move the directory
    if str(os.path.split(src)[0]) != str(out):
        shutil.move(os.path.splitext(src)[0], out)

    messagebox.showinfo("Finished", "Extraction Complete.\nSource: " + str(src) + "\nOutput: " + str(out))


def GUI_pack(src, out, endianness, compr_lvl):
    try:
        src = Path(src).resolve()
    except FileNotFoundError:
        messagebox.showerror("File Not Found", "The directory at " + src + " does not exist.")
        return

    try:
        out = Path(out).resolve()
    except FileNotFoundError:
        messagebox.showerror("File Not Found", "The file at " + out + " does not exist.")
        return

    src = os.path.abspath(src)
    pack(src, endianness, compr_lvl, out)
    messagebox.showinfo("Finsihed", "Packing Complete\nSource: " + str(src) + "\nOutput: " + str(out))



def main():
    # initialize variables
    lbl_font = ("Times New Roman", 16)

    # instantiates the primary window
    primary = Tk.Tk()
    primary.title("SARC Tool v0.4 GUI")
    primary.resizable(False, False)
    primary.option_add("*Dialog.msg.width", 600)

    # configure styles
    stl = Ttk.Style()

    if platform.system() == "Windows":
        stl.theme_use("vista")
    elif platform.system() == "Darwin":
        stl.theme_use("aqua")
    elif platform.system == "Linux":
        stl.theme_use("clam")

    stl.configure("TButton",
                  padding=3,
                  font=("Calibri", 11, "italic", "bold"))
    stl.configure("TEntry",
                  padding=[2, 1],
                  font=("Calibri", 11))

    tabCtrl = Ttk.Notebook(primary)

    ########## EXTRACT FRAME START ##########
    extract_frame = Ttk.Frame(tabCtrl)

    # source Label
    extract_src_lbl = Ttk.Label(extract_frame, text="Source File:", font=lbl_font)
    extract_src_lbl.grid(row=0, column=0, sticky="W", padx=8, pady=(10, 0))

    # source Entry
    extract_src_entry = Ttk.Entry(extract_frame, width=55)
    extract_src_entry.grid(row=1, column=0, padx=(10, 5), pady=3, ipady=3)

    # source Button
    extract_src_bttn = Ttk.Button(extract_frame, text="Select...", command=lambda: selFile(extract_src_entry))
    extract_src_bttn.grid(row=1, column=1, padx=(5, 10), pady=3)

    # output Label
    extract_out_lbl = Ttk.Label(extract_frame, text="Output Directory:", font=lbl_font)
    extract_out_lbl.grid(row=2, column=0, sticky="W", padx=8, pady=(10, 0))

    # output Entry
    extract_out_entry = Ttk.Entry(extract_frame, width=55)
    extract_out_entry.grid(row=3, column=0, padx=(10, 5), pady=3, ipady=3)

    #output Button
    extract_out_bttn = Ttk.Button(extract_frame, text="Select...", command=lambda: selDir(extract_out_entry))
    extract_out_bttn.grid(row=3, column=1, padx=(5, 10), pady=3)

    # extract file button
    extract_bttn = Ttk.Button(extract_frame, text="Extract", command=lambda: GUI_extract(extract_src_entry.get(), extract_out_entry.get()))
    extract_bttn.grid(row=4, column=0, sticky="W", padx=10, pady=(3, 6))
    ########## EXTRACT FRAME END ##########

    ########## PACK FRAME START #########
    pack_frame = Ttk.Frame(tabCtrl)

    # source Label
    pack_src_lbl = Ttk.Label(pack_frame, text="Source Directory:", font=lbl_font)
    pack_src_lbl.grid(row=0, column=0, sticky="W", padx=8, pady=(10, 0))

    # source Entry
    pack_src_entry = Ttk.Entry(pack_frame, width=55)
    pack_src_entry.grid(row=1, column=0, sticky="W", padx=(10, 5), pady=3, ipady=3)

    # source Button
    pack_src_bttn = Ttk.Button(pack_frame, text="Select...", command=lambda: selDir(pack_src_entry))
    pack_src_bttn.grid(row=1, column=1, sticky="W", padx=(5, 10), pady=3)

    # endianness Label
    endianness_lbl = Ttk.Label(pack_frame, text="Console:", font=lbl_font)
    endianness_lbl.grid(row=2, column=0, sticky="W", padx=8, pady=(10, 0))

    pack_rb_val = Tk.StringVar(None, '<')
    # Switch/3DS Radiobutton
    endianness_switch3ds_rb = Ttk.Radiobutton(pack_frame, text="Switch/3DS", value='<', variable=pack_rb_val)
    endianness_switch3ds_rb.grid(row=3, column=0, sticky="W", padx=8, pady=3)

    # Wii U Radiobutton
    endianness_wiiu_rb = Ttk.Radiobutton(pack_frame, text="Wii U", value='>', variable=pack_rb_val)
    endianness_wiiu_rb.grid(row=4, column=0, sticky="W", padx=8, pady=3)

    # compression level Label
    compr_lvl_lbl = Ttk.Label(pack_frame, text="Compression [0 - fastest/largest; 9 - slowest/smallest]:", font=lbl_font)
    compr_lvl_lbl.grid(row=5, column=0, columnspan=2, sticky="W", padx=8, pady=(10, 0))

    # compression level Spinbox
    compr_lvl_spnr = Ttk.Spinbox(pack_frame, from_=0, to=9, state="readonly", justify="center", font=("Serif", 11), width=10)
    compr_lvl_spnr.grid(row=6, column=0, sticky="W", padx=(10, 5), pady=3)

    # output Label
    pack_out_lbl = Ttk.Label(pack_frame, text="Output File:", font=lbl_font)
    pack_out_lbl.grid(row=7, column=0, sticky="W", padx=8, pady=(10, 0))

    # output Entry
    pack_out_entry = Ttk.Entry(pack_frame, width=55)
    pack_out_entry.grid(row=8, column=0, sticky="W", padx=(10, 5), pady=3, ipady=3)

    # output Button
    pack_out_bttn = Ttk.Button(pack_frame, text="Select...", command=lambda: saveFile(pack_out_entry))
    pack_out_bttn.grid(row=8, column=1, sticky="W", padx=(5, 10), pady=3)

    # pack Button
    pack_bttn = Ttk.Button(pack_frame, text="Pack", command=lambda: GUI_pack(pack_src_entry.get(), pack_out_entry.get(), pack_rb_val.get(), compr_lvl_spnr.get()))
    pack_bttn.grid(row=9, column=0, sticky="W", padx=10, pady=(3, 6))
    ########## PACK FRAME END ###########

    tabCtrl.add(extract_frame, text="Extract")
    tabCtrl.add(pack_frame, text="Pack")
    tabCtrl.pack(expand=True, fill="both")

    center(primary, 0, -50)
    Tk.mainloop()

if __name__ == '__main__':
    main()

标签: pythonpython-3.xtkintertypeerror

解决方案


我想到了。我需要使用ord(...)来自 Ttk.Spinbox 的值。我认为因为它是一个微调器,所以它会返回一个 int 而不是 str,但我想我错了。


推荐阅读