Veri dosyalarını PyInstaller (--onefile) ile gruplama


107

PyInstaller ile bir resim ve bir simge içeren tek dosyalık bir EXE oluşturmaya çalışıyorum. Hayatım boyunca onu kullanamam --onefile.

Yaparsam her şey --onedirçok iyi çalışıyor. Kullandığımda --onefile, referans verilen ek dosyaları bulamıyor (derlenmiş EXE'yi çalıştırırken). DLL'leri ve diğer her şeyi iyi bulur, sadece iki görüntüyü değil.

EXE çalıştırırken oluşturulan temp-dir'e baktım ( \Temp\_MEI95642\örneğin) ve dosyalar gerçekten de oradadır. EXE'yi bu geçici dizine bıraktığımda onları bulur. Çok kafa karıştırıcı.

Bu .specdosyaya eklediğim şey

a.datas += [('images/icon.ico', 'D:\\[workspace]\\App\\src\\images\\icon.ico',  'DATA'),
('images/loaderani.gif','D:\\[workspace]\\App\\src\\images\\loaderani.gif','DATA')]     

Bunları da alt klasörlere koymamaya çalıştığımı eklemeliyim, bir fark yaratmadı.

Düzenle: PyInstaller güncellemesi nedeniyle daha yeni yanıt doğru olarak işaretlendi.


11
çok teşekkür ederim! buradaki satır ( a.datas += ...) şu anda bana gerçekten yardımcı oldu. pyinstaller dokümantasyonu kullanım hakkında konuşuyor, COLLECTancak bu, kullanırken dosyaları ikiliye koyamıyor--onefile
Igor Serebryany

@IgorSerebryany: İkinci! Sadece aynı problemi yaşadım.
Hubro


1
Yürütme bittiğinde geçici klasörün kaybolduğunu göz önünde bulundurun, böylece içinde ne olduğunu kontrol etmek için program main
hithwen

Ayrıca bu yerde görmüş olduğum Tree () sözdizimini kullanmanın bir yolu var mı?
fatuhoku

Yanıtlar:


152

PyInstaller'ın daha yeni sürümleri envartık değişkeni ayarlamaz , bu nedenle Shish'in mükemmel cevabı çalışmayacaktır. Şimdi yol şu şekilde ayarlanır sys._MEIPASS:

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

10
Pyinstaller 2'yi python 2.7 ile kullanıyorum ve envs'de yok _MEIPASS2ama sys._MEIPASSiyi çalışıyor, yani +1. path = getattr(sys, '_MEIPASS', os.getcwd())
Öneriyorum

2
+1. Bunun için teşekkürler. Bir süredir _MEIPASS2 ortam değişkenini kullanmaya çalıştığımda, kodumu hala ortam değişkeni iken yazdım, çünkü çalıştığını hatırlıyorum. Geçenlerde yeniden derlediğimde aniden durdu.
Favil Orbedios

8
AttributeErrorDaha genel yerine yakalamanı tavsiye ederim Exception. Sistem içe aktarımını kaçırdığım ve sessizce varsayılan yolun varsayılan olduğu sorunlarla karşılaştım os.path.abspath.
Aaron

Sen benim çözmeye yardımcı olmak için mümkün olabilir sorunu .
Phillip

1
_MEIPASS'ın ayarlanmadığı durumda mevcut çalışma dizinini kullanmak yanlıştır. Cevabımı gör .
Jonathon Reinhart

51

pyinstaller verilerinizi geçici bir klasöre çıkarır ve bu dizin yolunu _MEIPASS2ortam değişkeninde depolar . Almak için _MEIPASS2paketlenmiş modunda dir ve çözdükten (geliştirme) modunda yerel dizin kullanmak, bunu kullanmaktan:

def resource_path(relative):
    return os.path.join(
        os.environ.get(
            "_MEIPASS2",
            os.path.abspath(".")
        ),
        relative
    )

Çıktı:

# in development
>>> resource_path("app_icon.ico")
"/home/shish/src/my_app/app_icon.ico"

# in production
>>> resource_path("app_icon.ico")
"/tmp/_MEI34121/app_icon.ico"

10
Bu nasıl, ne zaman ve nerede kullanılır?
gseattle

4
Bu komut dosyasını PyInstaller ile derlemeye çalıştığınız .py dosyasında kullanmalısınız. Bu kod parçacığını .spec dosyasına koymayın, bu işe yaramaz. Normalde yazdığınız yolu değiştirerek dosyalarınıza erişin resource_path("file_to_be_accessed.mp3"). PyInstaller'ın mevcut sürümü için max 'answer kullanmanız gerektiğine dikkat edin.
Exeleration-G

1
Bu cevap --one-fileseçeneği kullanmaya özel mi?
fatuhoku

Sen benim çözmeye yardımcı olmak için mümkün olabilir sorunu .
Phillip

_MEIPASS'ın ayarlanmadığı durumda mevcut çalışma dizinini kullanmak yanlıştır. Cevabımı gör .
Jonathon Reinhart

30

Diğer tüm yanıtlar , uygulamanın PyInstalled olmadığı (yani ayarlanmadığı) durumda geçerli çalışma dizinini kullanır sys._MEIPASS. Bu yanlıştır, çünkü uygulamanızı komut dosyanızın bulunduğu dizin dışındaki bir dizinden çalıştırmanızı engeller.

Daha iyi bir çözüm:

import sys
import os

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)

Teşekkürler Jon, fonksiyonun bugün bir problemi çözmeme yardımcı oldu. Sadece bir sorum var. Neden bazıları _MEIPASS yerine _MEIPASS2 yazsın? Daha önce 2'yi eklemeye çalıştığımda işe yaramadı.
Ahmed AbdelKhalek

Sanırım os.env['_MEIPASS2'](işletim sistemi ortamını kullanmak) dizini elde etmenin eski bir yöntemiydi. AFAIK sys._MEIPASSşu anda tek doğru yöntemdir.
Jonathon Reinhart

Merhaba, çözümünüz resource_path()ana komut dosyasındayken iyi çalışıyor. Bunun yerine bir modülde yazıldığında çalışmasını sağlamanın bir yolu var mı? Şu an itibariyle, kaynakları ana değil modülün bulunduğu klasörde almaya çalışacaktır.
Guimoute

1
@Guimoute, bu yanıttaki kodun tasarlandığı gibi çalıştığı gibi geliyor: kullandığı için kaynakları sağlayan modüle yerelleştiriyor __file__. Bir modülün kendi kapsamı dışındaki kaynaklara erişebilmesini istiyorsanız, içe aktaran kodun modülünüzün kullanması için onlara bir yol sağladığını uygulamanız gerekecektir, örneğin modül tarafından bir "set_resource_location ()" çağrısı yapan ithalatçı aramaları - bunun, pyinstaller kullanmadığınızda nasıl çalışmanız gerektiğinden farklı olduğunu düşünmeyin.
barny

@barny İpucu için teşekkürler! Bu çizgide bir şeyler deneyeceğim.
Guimoute

14

Belki bir adımı kaçırdım veya yanlış bir şey yaptım, ancak yukarıdaki yöntemler, PyInstaller ile veri dosyalarını tek bir exe dosyasına toplamadı. Yaptığım adımları paylaşmama izin verin.

  1. adım: sys ve os modüllerini içe aktararak yukarıdaki yöntemlerden birini py dosyanıza yazın. İkisini de denedim. Sonuncusu:

    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)
    
  2. adım: Bir file.spec dosyası oluşturmak için konsola pyi-makepec file.py yazın .

  3. adım: Aşağıdaki gibi veri dosyalarını eklemek için, file.spec dosyasını Notepad ++ ile açın:

    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)
    #Add the file like the below example
    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,
              #Turn the console option False if you don't want to see the console while executing the program.
              console=False,
              #Add an icon to the program.
              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')
    
  4. adım: Yukarıdaki adımları takip ettim, ardından özellik dosyasını kaydettim. Sonunda konsolu açtı ve pyinstaller file.spec yazın (benim durumumda, dosya = Dönüştürücü-GUI).

Sonuç: Dist klasöründe hala birden fazla dosya var.

Not: Python 3.5 kullanıyorum.

DÜZENLEME: Nihayet Jonathan Reinhart'ın yöntemiyle çalışıyor.

  1. adım: sys ve os içe aktararak aşağıdaki kodları python dosyanıza ekleyin.

    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)
    
  2. adım: Dosyanızın yolunu ekleyerek yukarıdaki işlevi çağırın:

    image_path = resource_path("Converter-GUI.ico")
  3. adım: Kodlarınızın yola ihtiyaç duyduğu yere fonksiyonu çağıran yukarıdaki değişkeni yazın. Benim durumumda:

        self.window.iconbitmap(image_path)
  4. adım: Konsolu python dosyanızla aynı dizinde açın, aşağıdaki gibi kodları yazın:

        pyinstaller --onefile your_file.py
  5. adım: python dosyasının .spec dosyasını açın ve a.datas dizisini ekleyin ve 3. adımda düzenlemeden önce yukarıda verilen simgeyi exe sınıfına ekleyin.
  6. adım: Yol dosyasını kaydedin ve çıkın. Spec ve py dosyasını içeren klasörünüze gidin. Konsol penceresini tekrar açın ve aşağıdaki komutu yazın:

        pyinstaller your_file.spec

6. adımdan sonra bir dosyanız kullanıma hazırdır.


Teşekkürler @dilde! Değil o a.datasadım 5'deki dizi dizeleri dizilerini alır bakınız pythonhosted.org/PyInstaller/spec-files.html#adding-data-files referans için.
Ian Campbell

Üzgünüm, mesajınızın bir kısmını da anlayamıyorum, diliyorum zayıf İngilizcem yüzünden. Bu kısım "a.datas değil ...." , 'a.datas olduğuna dikkat edin ... " yazmak istediniz mi? A.datas dizisine dize eklemekle ilgili yazdıklarımda bir sorun mu var?
dildeolupbiten

Oops! Dikkat edilmelidir ki ... ya, yazım hatası için özür dilerim. Adımlarınız benim için harika çalıştı :), bu bilgiyi belgelerinde veya başka bir yerde bulamadım.
Ian Campbell

8

Tüm yol kodumu önerildiği gibi yeniden yazmak yerine, çalışma dizinini değiştirdim:

if getattr(sys, 'frozen', False):
    os.chdir(sys._MEIPASS)

Kodunuzun başına bu iki satırı ekleyin, gerisini olduğu gibi bırakabilirsiniz.


2
Hayır. İyi uygulamalar çalışma dizinini nadiren değiştirmelidir. Daha iyi yollar var.
Jonathon Reinhart

3

Kabul edilen yanıtta küçük değişiklikler.

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)

    return os.path.join(os.path.abspath("."), relative_path)

_MEIPASS'ın ayarlanmadığı durumda mevcut çalışma dizinini kullanmak yanlıştır. Cevabımı gör .
Jonathon Reinhart

1

PyInstaller'da gördüğüm en yaygın şikayet / soru "kodum kesinlikle pakete dahil ettiğim bir veri dosyasını bulamıyor, nerede?" Ve kodunuzun ne / nerede olduğunu görmek kolay değil. çıkarılan kod geçici bir konumda olduğundan ve çıktığında kaldırıldığı için arıyor. @Jonathon Reinhart'ı kullanarak tek dosyanıza nelerin dahil olduğunu ve nerede olduğunu görmek için bu kod parçasını ekleyinresource_path()

for root, dirs, files in os.walk(resource_path("")):
    print(root)
    for file in files:
        print( "  ",file)

0

Mevcut cevapları kafa karıştırıcı buldum ve sorunun nerede olduğunu bulmak uzun zaman aldı. İşte bulduğum her şeyin bir derlemesi.

Uygulamamı çalıştırdığımda bir hata alıyorum Failed to execute script foo( foo.pyana dosyaysa). Bu sorunu gidermek için PyInstaller'ı ile çalıştırmayın --noconsole(veya değiştirmek main.speciçin console=False=> console=True). Bununla, yürütülebilir dosyayı bir komut satırından çalıştırın ve başarısızlığı göreceksiniz.

Kontrol edilmesi gereken ilk şey, fazladan dosyalarınızı doğru bir şekilde paketlemesidir. ('x', 'x')Klasörün xdahil edilmesini istiyormuş gibi tuple eklemelisiniz .

Kilitlendikten sonra Tamam'a tıklamayın. Windows kullanıyorsanız, Her Şeyi Ara'yı kullanabilirsiniz . Dosyalarınızdan birini arayın (örn. sword.png). Dosyaları açtığı geçici yolu bulmalısınız (örn. C:\Users\ashes999\AppData\Local\Temp\_MEI157682\images\sword.png). Bu dizine göz atabilir ve her şeyi içerdiğinden emin olabilirsiniz. Bu şekilde bulamazsanız, main.exe.manifest(Windows) veya python35.dll(Python 3.5 kullanıyorsanız ) gibi bir şey arayın .

Yükleyici her şeyi içeriyorsa, sonraki olası sorun G / Ç dosyasıdır: Python kodunuz dosyalar için geçici dizin yerine yürütülebilir dosyanın dizinine bakmaktadır.

Bunu düzeltmek için, bu sorunun yanıtlarından herhangi biri işe yarar. Şahsen, hepsinin işe yarayacak bir karışımını buldum: ana giriş noktası dosyanızdaki ilk şey dizini koşullu olarak değiştirin ve diğer her şey olduğu gibi çalışır:

if hasattr(sys, '_MEIPASS'): os.chdir(sys._MEIPASS)


1
Afedersiniz. Ancak dizinleri değiştirmek asla doğru cevap değildir. Bir kullanıcı uygulamaya giden bir yol sağlarsa, bunun geçerli dizine göre olmasını bekler. Bunu değiştirirseniz, yanlış olur.
Jonathan Reinhart

0

Dosyaları geçici dizin yerine çalıştırılabilir dosyanıza göre yerleştirmeye çalışıyorsanız, dosyayı kendiniz kopyalamanız gerekir. Ben de bu şekilde bitirdim.

https://stackoverflow.com/a/59415662/999943

Bir dosya sistemini DISTPATH ​​değişkenine kopyalayan özellik dosyasında bir adım eklersiniz.

Umarım yardımcı olur.


0

Bu konuyla uzun zamandır (çok, çok uzun) uğraşıyorum . Hemen hemen her kaynağı araştırdım ama kafamda işler bir düzene girmiyordu.

Son olarak, izlenecek kesin adımları anladığımı düşünüyorum, paylaşmak istedim.

Cevabımın bu soruya başkalarının cevapları hakkında bilgi kullandığına dikkat edin.

Bir python projesinin bağımsız bir yürütülebilir dosyası nasıl oluşturulur.

Farz edelim ki, bir proje_folder'ımız var ve dosya ağacı aşağıdaki gibi:

project_folder/
    main.py
    xxx.py # modules
    xxx.py # modules
    sound/ # directory containing the sound files
    img/ # directory containing the image files
    venv/ # if using a venv

Öncelikle, yollarınızı sound/ve img/klasörlerinizi değişkenler halinde sound_dirve img_diraşağıdaki gibi tanımladığınızı varsayalım:

img_dir = os.path.join(os.path.dirname(__file__), "img")
sound_dir = os.path.join(os.path.dirname(__file__), "sound")

Bunları aşağıdaki şekilde değiştirmelisiniz:

img_dir = resource_path("img")
sound_dir = resource_path("sound")

Nerede, resource_path()senaryonuzun üst kısmında şu şekilde tanımlanır:

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)

Venv kullanıyorsanız sanal ortamı etkinleştirin,

Eğer tarafından, henüz yapsam pyinstaller yükleyin: pip3 install pyinstaller.

Çalıştır: pyi-makespec --onefile main.pyderleme ve derleme işlemi için özellik dosyasını oluşturmak için.

Bu, dosya hiyerarşisini şu şekilde değiştirecektir:

project_folder/
    main.py
    xxx.py # modules
    xxx.py # modules
    sound/ # directory containing the sound files
    img/ # directory containing the image files
    venv/ # if using a venv
    main.spec

Açık (bir edior ile) main.spec:

Üstüne şunu ekleyin:

added_files = [

("sound", "sound"),
("img", "img")

]

Ardından, satırını şu şekilde datas=[],değiştirin:datas=added_files,

Yapılan işlemlerin ayrıntıları main.speciçin buraya bakın .

Çalıştırmak pyinstaller --onefile main.spec

Ve tüm olduğunu, Çalıştırabileceğiniz mainiçinde project_folder/distkendi klasöründe başka bir şey kalmadan, herhangi bir yerden. Yalnızca o maindosyayı dağıtabilirsiniz . Artık gerçek bir bağımsız .


@JonathonReinhart hala buralardaysanız, cevabımda fonksiyonunuzu kullandığımı size bildirmek istedim.
muyustan

0

Max ve bu gönderinin mükemmel cevabını kullanarak görüntüler veya ses ve kendi araştırmam / testler gibi ekstra veri dosyaları eklemekle ilgili olarak, bu tür dosyaları eklemenin en kolay yolunun ne olduğuna inandığımı anladım.

Canlı bir örnek görmek isterseniz , depom GitHub'da burada .

Not: Bu, pyinstaller ile --onefileveya -Fkomutunu kullanarak derlemek içindir.

Ortamım aşağıdaki gibidir.


Sorunu 2 adımda çözme

Sorunu çözmek için Pyinstaller'a uygulamayla "paketlenmesi" gereken fazladan dosyalara sahip olduğumuzu özellikle söylememiz gerekir.

Ayrıca 'göreceli' bir yol kullanmamız gerekiyor , böylece uygulama bir Python Komut Dosyası veya Frozen EXE olarak çalışırken düzgün çalışabilir.

Bununla birlikte, göreceli yollara sahip olmamızı sağlayan bir işleve ihtiyacımız var. Maks Yayınlanan işlevi kullanarak, ilgili yolu kolayca çözebiliriz.

def img_resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

Yukarıdaki işlevi bu şekilde kullanırdık, böylece uygulama bir Komut Dosyası VEYA Dondurulmuş EXE olarak çalışırken uygulama simgesi görünür.

icon_path = img_resource_path("app/img/app_icon.ico")
root.wm_iconbitmap(icon_path)

Bir sonraki adım, Pyinstaller'a, derleme sırasında fazladan dosyaları nerede bulacağımızı öğretmemiz gerektiğidir, böylece uygulama çalıştırıldığında bunlar geçici dizinde oluşturulur.

Bu sorunu belgelerde gösterildiği gibi iki şekilde çözebiliriz , ancak kişisel olarak kendi .spec dosyamı yönetmeyi tercih ediyorum, bu yüzden bunu yapacağız.

İlk olarak, bir .spec dosyanızın olması gerekir. Benim durumumda, ihtiyacım olanı pyinstallerfazladan argümanlar ile çalıştırarak yaratabildim , burada fazladan argümanlar bulabilirsiniz . Bu nedenle, benim özellik dosyam sizinkinden biraz farklı görünebilir ancak önemli kısımları açıkladıktan sonra hepsini referans için gönderiyorum.

added_files esasen kayıt düzeni en benim durumumda ben sadece TEK resim eklemek isteyen kulüpler içeren bir Liste, ancak kullanarak en ya jpg en png, çoklu ico en ekleyebilir('app/img/*.ico', 'app/img')şöyle de başka başlığın yaratabilir Youadded_files = [ (), (), ()]birden ithalatı var

Hangi dosya veya ne tür tanımlama grubu tanımlayıp ilk bölümü dosyası var bunları nerede bulacağını hem de eklemek istiyorum. Bunu CTRL + C olarak düşünün

Tuple'ın ikinci kısmı Pyinstaller'a 'app / img /' yolunu yapmasını ve dosyaları bu dizine, .exe dosyasını çalıştırdığınızda oluşturulan geçici dizine İLGİLİ yerleştirmesini söyler. Bunu CTRL + V olarak düşünün

Altındaa = Analysis([main... ,datas=added_filesbaşlangıçta öyle olduğunubelirledim,datas=[]ancak ithalat listesinin ithal olmasını istiyoruz, bu yüzden özel ithalatlarımızı geçiyoruz.

EXE için belirli bir simge istemediğiniz sürece bunu yapmanıza gerek yok, spec dosyasının altında Pyinstaller'a exe için uygulama simgemi seçenekle ayarlamasını söylüyorum icon='app\\img\\app_icon.ico'.

added_files = [
    ('app/img/app_icon.ico','app/img/')
]
a = Analysis(['main.py'],
             pathex=['D:\\Github Repos\\Processes-Killer\\Process Killer'],
             binaries=[],
             datas=added_files,
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='Process Killer',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True , uac_admin=True, icon='app\\img\\app_icon.ico')

EXE'ye derleniyor

Ben çok tembelim; Yazmak zorunda olduğumdan daha fazla bir şeyler yazmayı sevmiyorum. Sadece tıklayabileceğim bir .bat dosyası oluşturdum. Bunu yapmak zorunda değilsiniz, bu kod bir komut istemi kabuğunda onsuz gayet iyi çalışacaktır.

.Spec dosyası tüm derleme ayarlarımızı ve bağımsız değişkenlerimizi (seçenekler olarak da bilinir) içerdiğinden, bu .spec dosyasını Pyinstaller'a vermemiz yeterlidir.

pyinstaller.exe "Process Killer.spec"

0

Diğer bir çözüm, verilerinizi (dosyalar / klasörler) yürütülebilir dosyanın depolandığı dizine kopyalayacak (veya taşıyacak) bir çalışma zamanı kancası oluşturmaktır. Kanca, uygulamanızın çalıştırılmasından hemen önce neredeyse her şeyi yapabilen basit bir python dosyasıdır. Bunu ayarlamak için, --runtime-hook=my_hook.pypyinstaller seçeneğini kullanmalısınız . Dolayısıyla, verilerinizin bir görüntü klasörü olması durumunda, şu komutu çalıştırmalısınız:

pyinstaller.py --onefile -F --add-data=images;images --runtime-hook=cp_images_hook.py main.py

Cp_images_hook.py şöyle bir şey olabilir:

import sys
import os
import shutil

path = getattr(sys, '_MEIPASS', os.getcwd())

full_path = path+"\\images"
try:
    shutil.move(full_path, ".\\images")
except:
    print("Cannot create 'images' folder. Already exists.")

Her yürütmeden önce, resimler klasörü geçerli dizine (_MEIPASS klasöründen) taşınır, böylece yürütülebilir dosya her zaman ona erişebilir. Bu şekilde projenizin kodunu değiştirmenize gerek yoktur.

İkinci Çözüm

Bazı geliştiricilere göre iyi bir uygulama olmayan, çalışma zamanı-kanca mekanizmasından faydalanabilir ve mevcut dizini değiştirebilirsiniz, ancak iyi çalışıyor.

Kanca kodu aşağıda bulunabilir:

import sys
import os

path = getattr(sys, '_MEIPASS', os.getcwd())   
os.chdir(path)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.