Tengo problemas para escribir una función que pueda tomar una lista de elementos de tarfile mediante el método .getmembers() y colocarlos en una estructura de árbol adecuada (archivos dentro de carpetas y subcarpetas) en el widget Treeview. Encontré una publicación similar a la que quería: Tkinter: Treeview widget, pero no pude obtener se adaptó para ver archivos.
El problema con la solución a la que hice referencia es que usa os para recorrer un directorio dado e insertar los elementos en una vista de árbol. Por supuesto, eso no funcionará en un archivo tar porque es un archivo, no una carpeta, así que cuando intenté modificar la solución, almacené los miembros del archivo tar en una lista e intenté alimentarlo a través de la función, pero simplemente no funciona para mí.

Esencialmente, necesito ayuda para escribir una función que tome una lista de nombres de directorios y archivos y pueda insertar directorios principales en la raíz de la vista de árbol, y elementos secundarios en sus carpetas que contienen.

import os
import tkinter as tk
import tkinter.ttk as ttk
import tarfile

window = tk.Tk()
window.title("Testing")
window.geometry("500x500")

tree = ttk.Treeview(window)
tree.pack()
tree.heading('#0', text="Item")
tree.column('#0', width=495)

# Get TAR items
with tarfile.TarFile("testing.tar") as topen:
    tarlist = topen.getmembers()

# Get our first directory in the list and remove it from stack
for i in tarlist:
    if i.isdir() == True:
        start_node = i.name
        del tarlist[tarlist.index(i)]
        break

# Insert root folder
root_node = tree.insert('', 'end', text=start_node)

def insert():
    # Go through the rest of the member list and put the member in the proper place
    # within the tree structure

window.mainloop()

-1
Jimmy-John 19 dic. 2019 a las 08:09

2 respuestas

La mejor respuesta

La idea es utilizar la ruta completa del elemento como su iid en el árbol para que pueda obtener tanto el elemento primario del elemento como la etiqueta del elemento con parent, label = os.path.split(item.path).

De acuerdo con .getmembers() docstring,

Devuelve los miembros del archivo como una lista de objetos TarInfo. La lista tiene el mismo orden que los miembros del archivo.

Por lo tanto, no debe preocuparse por la existencia del padre, se habrá creado antes si pasa por tarlist con un bucle for, como en el código a continuación.

import os
import tkinter as tk
import tkinter.ttk as ttk
import tarfile

window = tk.Tk()
window.title("Testing")
window.geometry("500x500")

tree = ttk.Treeview(window)
tree.pack()
tree.heading('#0', text="Item")
tree.column('#0', width=495)

# Get TAR items
with tarfile.TarFile("testing.tar") as topen:
    tarlist = topen.getmembers()


def insert():
    for item in tarlist:
        parent, label = os.path.split(item.path)
        tree.insert(parent, 'end', iid=item.path, text=label)

insert()
window.mainloop()
0
j_4321 19 dic. 2019 a las 12:08

Gracias a j_4321, esto es lo que hice para obtener lo que deseaba. Dividí la lista de tar en una lista de tardanzas y tarfiles, luego agregué las tardanzas primero porque quería que se ordenaran jerárquicamente. Los tarfiles vinieron luego y fueron insertados en su lugar apropiado. Utilicé un controlador de excepciones para detectar cualquier anomalía en la que un archivo tenga el mismo nombre que un directorio, y evite usar iid en esa instancia. El resultado es una vista bien estructurada de un archivo TAR, luego se agregarían iconos de carpeta junto a los elementos identificados como directorios y qué no hacer que se vea presentable.

tardirs = []
tarfiles = []

for i in tarlist:
    if i.isdir() == True:
        tardirs.append(i)
    else:
        tarfiles.append(i)

def insert():
    for item in tardirs:
        parent, label = os.path.split(item.path)
        try:
            tree.insert(parent, 'end', iid=item.path, text=label)
        except Exception:
            tree.insert(parent, 'end', text=label)
    for item in tarfiles:
        parent, label = os.path.split(item.path)
        try:
            tree.insert(parent, 'end', iid=item.path, text=label)
        except Exception:
            tree.insert(parent, 'end', text=label)
0
Jimmy-John 20 dic. 2019 a las 03:59