analitics

Pages

Showing posts with label zipfile. Show all posts
Showing posts with label zipfile. Show all posts

Tuesday, June 9, 2026

Python Qt : Simple script to install the G'MIC archive to the Krita folder.

Today, this simple script will install the G'MIC archive to the Krita folder:
import sys
import os
import zipfile
import shutil
import subprocess
from PyQt6.QtWidgets import (
    QApplication, QWidget, QPushButton, QFileDialog,
    QVBoxLayout, QLabel, QMessageBox
)

class GMICInstaller(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("GMIC Installer for Krita")

        self.gmic_zip = ""
        self.krita_folder = ""

        layout = QVBoxLayout()

        self.label_zip = QLabel("GMIC archive: Not selected")
        self.label_krita = QLabel("Krita folder: Not selected")

        btn_zip = QPushButton("Select GMIC Archive (.zip)")
        btn_zip.clicked.connect(self.select_gmic_zip)

        btn_krita = QPushButton("Select Krita Folder")
        btn_krita.clicked.connect(self.select_krita_folder)

        btn_install = QPushButton("Install on Krita")
        btn_install.clicked.connect(self.install_gmic)

        layout.addWidget(self.label_zip)
        layout.addWidget(btn_zip)
        layout.addWidget(self.label_krita)
        layout.addWidget(btn_krita)
        layout.addWidget(btn_install)

        self.setLayout(layout)

    def select_gmic_zip(self):
        file, _ = QFileDialog.getOpenFileName(self, "Select GMIC ZIP", "", "ZIP Files (*.zip)")
        if file:
            self.gmic_zip = file
            self.label_zip.setText(f"GMIC archive: {file}")

    def select_krita_folder(self):
        folder = QFileDialog.getExistingDirectory(self, "Select Krita Folder")
        if folder:
            self.krita_folder = folder
            self.label_krita.setText(f"Krita folder: {folder}")

    def install_gmic(self):
        if not self.gmic_zip or not self.krita_folder:
            QMessageBox.warning(self, "Error", "Select both GMIC archive and Krita folder first.")
            return

        # Step 1: Extract GMIC ZIP
        extract_path = os.path.join(os.getcwd(), "gmic_extracted")
        if os.path.exists(extract_path):
            shutil.rmtree(extract_path)
        os.makedirs(extract_path)

        with zipfile.ZipFile(self.gmic_zip, 'r') as zip_ref:
            zip_ref.extractall(extract_path)

        # Step 2: Find GMIC folder inside extracted content
        gmic_folder = None
        for root, dirs, files in os.walk(extract_path):
            if "gmic_krita_qt.dll" in files or "gmic_qt.exe" in files:
                gmic_folder = root
                break

        if not gmic_folder:
            QMessageBox.critical(self, "Error", "GMIC plugin files not found in archive.")
            return

        # Step 3: Find Krita plugin folders
        possible_paths = [
            os.path.join(self.krita_folder, "share", "krita", "pykrita"),
            os.path.join(self.krita_folder, "lib", "krita", "plugins"),
            os.path.join(os.getenv("APPDATA"), "krita", "pykrita")
        ]

        installed = False

        for path in possible_paths:
            if os.path.exists(path):
                try:
                    shutil.copytree(gmic_folder, os.path.join(path, "gmic_qt"), dirs_exist_ok=True)
                    installed = True
                except Exception as e:
                    print("Copy error:", e)

        if not installed:
            QMessageBox.critical(self, "Error", "Could not find a valid Krita plugin folder.")
            return

        # Step 4: Launch Krita
        krita_bin = os.path.join(self.krita_folder, "bin", "krita.exe")
        if os.path.exists(krita_bin):
            subprocess.Popen([krita_bin])
        else:
            QMessageBox.warning(self, "Warning", "GMIC installed, but Krita executable not found.")

        QMessageBox.information(self, "Success", "GMIC successfully installed into Krita!")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = GMICInstaller()
    window.show()
    sys.exit(app.exec())

Saturday, May 16, 2026

Python 3.10.11 : about the windows embeddable portable Python distributions fix pip.

Let's learn about the windows embeddable portable Python distributions.
  • The Windows embeddable Python distribution is a minimal, self‑contained build of Python designed to run entirely from its own directory without installation.
  • This distribution does not modify system settings, environment variables, or the Windows registry.
  • Its structure makes it suitable for embedding Python inside applications or distributing Python as a portable runtime.
Typical use cases
  • Bundling Python with standalone software that requires a predictable runtime environment.
  • Running Python scripts in isolated environments where system‑wide installations must not be affected.
  • Deploying portable utilities that must operate from removable storage or restricted systems.
When the embeddable distribution is not ideal
  • General development workflows that rely on pip, external packages, or virtual environments.
  • Educational or experimental setups where tutorials assume a standard Python installation.
  • Projects that depend on automatic module discovery and dynamic package management.
The Role of python310._pth
  • The file named python310._pth controls how the embeddable distribution locates and loads Python modules.
  • When this file is present, Python enters an isolated mode in which only the paths explicitly listed inside the file are used.
  • If the file does not include the line import site, the standard site initialization process is disabled, preventing access to site‑packages.
Typical structure of python310._pth
python310.zip
.
import site
Explanation of each entry
  • python310.zip specifies the location of the standard library packaged as a zip archive.
  • . allows Python to import modules from the root directory of the distribution.
  • import site activates the site module, enabling automatic loading of Lib and site‑packages.
Enabling pip and external modules
  • The embeddable distribution does not load external modules unless the appropriate paths are added to python310._pth.
  • To enable pip and other installed packages, the file must include the Lib and Lib\site-packages directories.
Example of a Fully Enabled python310._pth
python310.zip
.
Lib
Lib\site-packages
import site
Testing the updated configuration
python -c "import sys; print(sys.path)"
Installing pip after enabling site‑packages
  • Once the module paths are active, pip can be installed using standard methods.
python get-pip.py
python -m ensurepip
Verifying pip
python -m pip --version
Advantages of the embeddable distribution:
  • Provides a predictable and isolated runtime environment.
  • Does not interfere with system‑wide Python installations.
  • Ideal for packaging Python with standalone applications.
Disadvantages of the embeddable distribution:
  • pip and external modules are disabled by default.
  • Requires manual configuration to behave like a standard installation.
  • Not suitable for typical development workflows.
Clean, Ready‑to‑Use python310._pth File
python310.zip
.
Lib
Lib\site-packages
import site
This will fix the embeddable distribution, let's use this source code to fix the pip tool:
import os
import urllib.request
import zipfile
import shutil

PYTHON_DIR = r"C:\python-3_10_11"
SITE = fr"{PYTHON_DIR}\Lib\site-packages"

print("[INFO] Descarc pip.zip...")
urllib.request.urlretrieve(
    "https://github.com/pypa/pip/archive/refs/heads/main.zip",
    "pip.zip"
)

print("[INFO] Dezarhivez pip.zip...")
with zipfile.ZipFile("pip.zip", "r") as z:
    z.extractall("pip_src")

pip_src = "pip_src/pip-main/src/pip"

print("[INFO] Copiez pip în site-packages...")
target = os.path.join(SITE, "pip")
if os.path.exists(target):
    shutil.rmtree(target)

shutil.copytree(pip_src, target)

print("[INFO] Creez pip.dist-info minimal...")
dist = os.path.join(SITE, "pip.dist-info")
os.makedirs(dist, exist_ok=True)

with open(os.path.join(dist, "METADATA"), "w") as f:
    f.write("Name: pip\nVersion: 0\n")

print("[OK] pip instalat direct în Python.")
print("Rulează acum:")
print("   python -m pip --version")
Let's tun and test with PyQt6:
python fix_pip.py
[INFO] Descarc pip.zip...
[INFO] Dezarhivez pip.zip...
[INFO] Copiez pip în site-packages...
[INFO] Creez pip.dist-info minimal...
[OK] pip instalat direct în Python.
Rulează acum:
   python -m pip --version

python -m pip --version
pip 26.2.dev0 from C:\python-3_10_11\Lib\site-packages\pip (python 3.10)

python -m pip install PyQt6
Collecting PyQt6
  Downloading pyqt6-6.11.0-cp310-abi3-win_amd64.whl.metadata (2.2 kB)
...
Installing collected packages: PyQt6-Qt6, PyQt6-sip, PyQt6
Successfully installed PyQt6-6.11.0 PyQt6-Qt6-6.11.1 PyQt6-sip-13.11.1

Sunday, July 14, 2019

Python 3.7.3 : Simple tests with zipfile python module.

You can read about this python module here.
The ZIP file format is a common archive and compression standard. This module provides tools to create, read, write, append, and list a ZIP file. Any advanced use of this module will require an understanding of the format, as defined in PKZIP Application Note.

This module does not currently handle multi-disk ZIP files. It can handle ZIP files that use the ZIP64 extensions (that is ZIP files that are more than 4 GiB in size). It supports decryption of encrypted files in ZIP archives, but it currently cannot create an encrypted file. Decryption is extremely slow as it is implemented in native Python rather than C.

C:\Python373> python -m zipfile -c test.zip test.html  textalongpath.pdf
C:\Python373> python -m zipfile -c test_folder.zip test.html  temp
C:\Python373>python -m zipfile -l  test.zip
File Name                                             Modified             Size
test.html                                      2019-07-11 10:46:58         6115
textalongpath.pdf                              2019-06-08 22:55:50           84

C:\Python373>python -m zipfile -l  test_folder.zip
File Name                                             Modified             Size
test.html                                      2019-07-11 10:46:58         6115
temp/                                          2019-07-07 21:36:42            0
temp/wlop/                                     2019-07-07 21:36:42            0
This lines of code will create two archives named test.zip and test_folder.zip with the files shown on each command.
For extraction, is need to use the -e argument:
C:\Python373>python -m zipfile -e test.zip zipfiles/

C:\Python373>python -m zipfile -e test_folder.zip zipfiles/

C:\Python373>cd zipfiles

C:\Python373\zipfiles>dir
...
Let's using this python module inside python:
C:\Python373>python.exe
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 21:26:53) [MSC v.1916 32 bit (Inte
l)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import zipfile
>>> import datetime
>>> my_zip = zipfile.ZipFile('test.zip','r')
>>> print (my_zip.namelist())
['test.html', 'textalongpath.pdf']
>>> def print_info(archive_name):
...     my_zip = zipfile.ZipFile(archive_name)
...     for info in my_zip.infolist():
...             print (info.filename)
...             print ('Comment: ', info.comment)
...             print ('Modified: ', datetime.datetime(*info.date_time))
...             print ('System: ', info.create_system, '(0 = Windows, 3 = Unix)'
)
...             print ('ZIP version: ', info.create_version)
...             print ('Compressed: ', info.compress_size, 'bytes')
...             print ('Uncompressed: ', info.file_size, 'bytes')
...
>>> print_info('test_folder.zip')
test.html
Comment:  b''
Modified:  2019-07-11 10:46:58
System:  0 (0 = Windows, 3 = Unix)
ZIP version:  20
Compressed:  1679 bytes
Uncompressed:  6115 bytes
temp/
Comment:  b''
Modified:  2019-07-07 21:36:42
...
Extract all files from an archive:
>>> from zipfile import ZipFile
>>> with ZipFile('test.zip','r') as zipObj:
...     zipObj.extractall()
Extract files by extension:
>>> with ZipFile('test.zip', 'r') as zipObj:
...    listOfFileNames = zipObj.namelist()
...    for fileName in listOfFileNames:
...        if fileName.endswith('.html'):
...            zipObj.extract(fileName, 'new.html')
...
'new.html\\test.html'
Create a new arhive named The_new.zip and add the new.html file on it.
>>> zipObj = ZipFile('The_new.zip','w')
>>> zipObj.write('new.html')
>>> zipObj.close()
>>> print_info('The_new.zip')
new.html/
Comment:  b''
Modified:  2019-07-14 22:15:58
System:  0 (0 = Windows, 3 = Unix)
ZIP version:  20
Compressed:  0 bytes
Uncompressed:  0 bytes