Harici dosyalar içeren GUI'yi PyInstaller ile tek bir EXE dosyasına çevirmek

Merhaba arkadaşlar,
Harici dosyalar içeren GUI’li Python dosyalarını PyInstaller ile exe dosyasına çevirmeyi öğrendim ancak tek bir exe dosyasına çeviremedim henüz. Konuyu stackoverflow sitesinde araştırdım ve
birden çok başlık buldum. Mesela aşağıda linki verilmiş olan başlıkta birkaç çözüm yöntemi öneriliyor ancak denemelerim başarısızlıkla sonuçlandı.
İlgili sayfa şu:
İzlediğim yöntemi ilgili başlığa yazdım ancak henüz cevap gelmedi. Belki çözüm yolunu siz biliyorsunuzdur. Yanlış yaptığım veya atladığım bir adım varsa yardımcı olursanız sevinirim.
İzlediğim yöntem aşağıdaki gibiydi:

Adım 1: Stackoverflow’da önerilen yöntemlerden her birini Py uzantılı dosyanın içine os ve sys modüllerini içe aktararak yazdım, aşağıdaki fonksiyonu ikon yolunun parametresini vererek çağırdım: Son yazdığım kod aşağıdaki gibidir:

def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

Adım 2: Python dosyasının bulunduğu dizinde konsol ekranını açıp ekrana pyi-makespec dosya_ismi.py yazarak ilgili Python dosyasının .spec uzantılı dosyasını oluşturdum.

Adım 3: spec dosyasını Notepad++ yardımıyla açtım. Aşağıdaki gibi kodlar barınıyor bu dosyanın içinde, eklediğim kısımlardan önce yorum satırları var:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['C:\\Users\\TCK\\Desktop\\Projeler\\Converter-GUI.py'],
             pathex=['C:\\Users\\TCK\\Desktop\\Projeler'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
#Exe dosyasına eklemek istediğimiz harici dosyayı aşağıdaki satırdaki gibi ekledim.
a.datas += [('Converter-GUI.ico', 'C:\\Users\\TCK\\Desktop\\Projeler\\Converter-GUI.ico', 'DATA')]
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          exclude_binaries=True,
          name='Converter-GUI',
          debug=False,
          strip=False,
          upx=True,
          #Konsolun değerine False verirsek konsol iptal ediliyor.
          console=False,
          #Eklemek istediğimiz ikonu da bu şekilde yazıyoruz.
          icon='C:\\Users\\TCK\\Desktop\\Projeler\\Converter-GUI.ico')
		  
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='Converter-GUI')

Adım 4: Yukarıda gösterilen değişiklikleri yaptıktan sonra spec dosyasını kaydettim. Sonra konsolu yine Python dosyasının bulunduğu dizinde açtım ve ekrana bu sefer pyinstaller C:\Users\TCK\Desktop\Projeler\Converter-GUI.spec yazdım. Exe dosyasını oluşturdu ancak dist klasörünün içinde halen çok sayıda dosya var.

Daha sonra pyinstaller --onefile C:\Users\TCK\Desktop\Projeler\Converter-GUI.spec şeklinde yapmayı denedim, sonuç yine istediğim gibi olmadı. Acaba bu konuda yardımcı olabilecek arkadaşlar var mı?

2 Beğeni

PyInstaller sitesinden bir alıntı:

In one-file mode, there is no call to COLLECT, and the EXE instance receives all of the scripts, modules and binaries.
Yukarıdaki spec dosyası içindeki kodlarda collect isimli bir sınıf var. Yukarıda yazılana göre collect sınıfının olduğu dosyalarda --onefile metodu kullanılamıyor. Ancak collect kısmı da silindiği taktirde, program çalışmıyor. Metnin birkaç satır aşağısında şöyle bir yazı var:
PyInstaller supports a more advanced (and complex) way of adding files to the bundle that may be useful for special cases. See The TOC and Tree Classes below.
İlgili sayfanın adresi şu: şu Okumayı henüz daha bitirmedim ama sonuç olarak istediğim değişikliği yapabilirsem burada paylaşırım.
1 Beğeni

Sorun çözülmüştür.
Sorunun çözümünde aşağıdaki yol izlenmiştir.

Adım 1: Python dosyasının içinde aşağıdaki fonksiyonu tanımlıyoruz:

import os, sys
def kaynak_yolu(goreceli_yol):
    temel_yol = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(temel_yol, goreceli_yol)

Adım 2: Fonksiyonu tanımladıktan sonra, herhangi bir değişken adı belirliyoruz ve değişkenimizin değeri olarak fonksiyonu yazıyoruz. Fonksiyonun parametre kısmına ise harici dosyamızın göreceli yolunu tırnak içerisinde aşağıdaki örnekte olduğu gibi belirtiyoruz.

image = kaynak_yolu("Converter-GUI.ico")

Adım 3: Daha sonra ise programımızda, bu ikonu adres olarak verdiğimiz yere, değişken adını yazıyoruz: Benim örneğimde ikonun adresinin geçtiği ilgili yer aşağısı:

self.window.iconbitmap(image)

Adım 4: Python dosyamızın bulunduğu dizinde konsol ekranını çalıştırıyoruz ve aşağıdaki komutları yazıyoruz.

pyinstaller --onefile dosya_ismi.py

Adım 5: Dosyamız oluştu ancak şu haliyle çalışmayacaktır. PyInstaller exe dosyasını oluştururken spec adlı bir dosya oluşturur. Bu dosyayı açıyoruz ve ilk mesajda 3. adımda verilen eklemeleri yapıyoruz:

a.datas += [('Converter-GUI.ico', 'C:\\Users\\TCK\\Desktop\\Projeler\\Converter-GUI.ico', 'DATA')]

ve,

icon='C:\\Users\\TCK\\Desktop\\Projeler\\Converter-GUI.ico'

Not-1: icon ekleme işlemini dilerseniz konsol ekranında da yapabilirsiniz.

Not-2: İlk mesajda verilen spec dosyasının içinde COLLECT sınıfı vardı. Ancak python dosyamızı --onefile ile dönüştürdüğümüzde .spec dosyasının içinde artık COLLECT sınıfı yer almıyor.

Adım 6: Konsol ekranını yine açıyoruz bu kez aşağıdaki komutları yazıyoruz:

pyinstaller dosya_ismi.spec

Son adımdan sonra artık harici dosyalar içeren GUI’li tek bir exe dosyamız var.

Not-3: Bu exe dosyası acaba sadece benim bilgisayarımda mı çalışıyor diye merak ettim, kardeşimin bilgisayarına bu exe dosyasını aktardım. Orada da çalıştı.

Not-4: Öğrendiğim kadarıyla tek bir klasör içinde birden çok dosya ile çalışan bir program, birden çok dosyayı içinde barındıran bir programa göre daha hızlı açılıyor.

8 Beğeni

Sorunun çözümünü sormana rağmen kendin cevaplamışsın. Çok yararlı bir başlık oldu. İşaretliyorum…

bende bu kadar gelişebilecek miyim acaba.
Hocam başarılar…

Teşekkür ederim. Araştırdığınız ve öğrendiklerinizle uygulamalar yaptığınız sürece gelişiminiz devam eder kanaatindeyim, siz yeterki öğrenmek isteyin. Size de başarılar dilerim.

2 Beğeni

haklısınız teşekkürler iyi akşamlar.