DEV Community

Mate Technologies
Mate Technologies

Posted on

Build a Professional Archive Extractor with Python (Drag & Drop + EXE)

In this tutorial, we’ll build QuickExtract v2.0.0 — a modern batch archive extractor with:

Drag & Drop support

Pause / Resume

Stop button

Real-time progress

Error logging

Windows EXE build

🚀 Option 1 — Download the Ready-to-Use EXE

If you don’t want to set up Python, download the compiled Windows version:

https://github.com/rogers-cyber/QuickExtract/releases

✔ No Python required
✔ Portable
✔ Double-click to run

💻 Option 2 — Clone the Source Code
git clone https://github.com/rogers-cyber/QuickExtract.git
cd QuickExtract

Install dependencies:

pip install ttkbootstrap patool tkinterdnd2
Enter fullscreen mode Exit fullscreen mode

Then run:

python QuickExtract.py
Step 1 — Import Required Modules

We need:

Tkinter (GUI)

ttkbootstrap (modern theme)

patool (archive extraction)

threading (background tasks)

queue (safe UI updates)

tkinterdnd2 (drag & drop)

import os
import sys
import threading
import time
import traceback
from queue import Queue, Empty
from tkinter import filedialog, messagebox
import ttkbootstrap as tb
import patoolib
import tkinter as tk
from tkinterdnd2 import DND_FILES, TkinterDnD
Step 2 — Application Configuration

Define the app name and version:

APP_NAME = "QuickExtract - Archive Extractor"
APP_VERSION = "2.0.0"
Enter fullscreen mode Exit fullscreen mode

Create the main window with drag-and-drop support:

app = TkinterDnD.Tk()
app.title(f"{APP_NAME} {APP_VERSION}")
app.geometry("1000x600")

tb.Style("darkly")
Enter fullscreen mode Exit fullscreen mode

Step 3 — Utility Functions

These help with:

EXE compatibility

Error logging

About dialog

def resource_path(file_name):
    base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, file_name)

def log_error():
    with open("error.log", "a", encoding="utf-8") as f:
        f.write(traceback.format_exc() + "\n")
Enter fullscreen mode Exit fullscreen mode

Step 4 — Add a Menu

menubar = tb.Menu(app)
help_menu = tb.Menu(menubar, tearoff=0)

help_menu.add_command(label="About", command=lambda:
    messagebox.showinfo(
        "About",
        f"{APP_NAME} v{APP_VERSION}\nSupports 70+ formats."
    )
)

menubar.add_cascade(label="Help", menu=help_menu)
app.config(menu=menubar)
Enter fullscreen mode Exit fullscreen mode

Step 5 — Threading & Queue Setup

We never update the UI directly from a thread.

Instead, we use a Queue:

stop_flag = False
pause_flag = False
ui_queue = Queue()
Enter fullscreen mode Exit fullscreen mode

Step 6 — Archive Selection Panel

Create a listbox to display selected archives:

archive_list = []
output_path = tb.StringVar()

frame1 = tb.Labelframe(app, text="Archive Selection", padding=10)
frame1.pack(fill="x", padx=10, pady=6)

archive_listbox = tk.Listbox(frame1, height=6)
archive_listbox.pack(fill="x")
Enter fullscreen mode Exit fullscreen mode

Add files:

def add_archives():
    files = filedialog.askopenfilenames(title="Select Archives")
    for f in files:
        if f not in archive_list:
            archive_list.append(f)
            ui_queue.put(("add", f))
Enter fullscreen mode Exit fullscreen mode

Step 7 — Drag & Drop Support

Enable drop functionality:

archive_listbox.drop_target_register(DND_FILES)
archive_listbox.dnd_bind('<<Drop>>', lambda e: drop(e))

def drop(event):
    files = app.tk.splitlist(event.data)
    for f in files:
        if os.path.isfile(f):
            archive_list.append(f)
            ui_queue.put(("add", f))
Step 8 — Progress Bar
frame2 = tb.Labelframe(app, text="Progress", padding=8)
frame2.pack(fill="x", padx=10)

progress_var = tb.IntVar()

tb.Progressbar(
    frame2,
    variable=progress_var,
    maximum=100,
    length=500
).pack(side="left", padx=10)

status_lbl = tb.Label(frame2, text="Status: Ready")
status_lbl.pack(side="left", padx=10)
Enter fullscreen mode Exit fullscreen mode

Step 9 — Extraction Logic (Background Thread)

This runs in a separate thread to keep the UI responsive.

def extract_archives():
    global stop_flag, pause_flag
    stop_flag = pause_flag = False

    total_files = len(archive_list)
    if total_files == 0:
        messagebox.showerror("Error", "No archives selected.")
        return

    for idx, archive in enumerate(archive_list, 1):

        if stop_flag:
            ui_queue.put(("log", "Stopped by user."))
            break

        while pause_flag:
            time.sleep(0.1)

        ui_queue.put(("log", f"Extracting: {archive}"))

        try:
            patoolib.extract_archive(archive, interactive=False)
            ui_queue.put(("log", f"Completed: {archive}"))
        except Exception:
            log_error()
            ui_queue.put(("log", f"Failed: {archive}"))

        percent = int((idx / total_files) * 100)
        ui_queue.put(("progress", percent))

    ui_queue.put(("complete", "Done"))
Enter fullscreen mode Exit fullscreen mode

Step 10 — UI Queue Processor

Safely update UI from the main thread:

def process_ui_queue():
    try:
        while True:
            cmd, data = ui_queue.get_nowait()

            if cmd == "add":
                archive_listbox.insert("end", data)

            elif cmd == "progress":
                progress_var.set(data)

            elif cmd == "log":
                print(data)

            elif cmd == "complete":
                status_lbl.config(text="Finished")

    except Empty:
        pass

    app.after(100, process_ui_queue)
Enter fullscreen mode Exit fullscreen mode

Start the queue processor:

app.after(100, process_ui_queue)
Step 11 — Run Extraction in Thread
tb.Button(
    app,
    text="Extract",
    command=lambda: threading.Thread(
        target=extract_archives,
        daemon=True
    ).start()
).pack(pady=10)
Enter fullscreen mode Exit fullscreen mode

Step 12 — Build Windows EXE

Install PyInstaller:

pip install pyinstaller
Enter fullscreen mode Exit fullscreen mode

Build:

pyinstaller --onefile --windowed --name "QuickExtract" QuickExtract.py

Your EXE will be inside:

dist/QuickExtract.exe
🎯 Final Result

You now have:

✔ Drag & Drop archive extractor
✔ Background threaded extraction
✔ Pause / Stop support
✔ Real-time progress
✔ Windows standalone EXE

📦 Project Links

Clone source:

https://github.com/rogers-cyber/QuickExtract

Download EXE:

https://github.com/rogers-cyber/QuickExtract/releases

Top comments (0)