PyInstaller (-onefile)로 데이터 파일 번들링


107

이미지와 아이콘을 포함하는 PyInstaller로 한 파일 EXE를 빌드하려고합니다. 나는 내 삶을 위해 그것을 작동시킬 수 없습니다 --onefile.

내가 할 경우 --onedir모든 것이 잘 작동합니다. 를 사용 --onefile하면 참조 된 추가 파일을 찾을 수 없습니다 (컴파일 된 EXE를 실행할 때). 두 이미지가 아닌 DLL과 다른 모든 것을 찾습니다.

EXE ( \Temp\_MEI95642\예를 들어)를 실행할 때 생성 된 temp-dir을 살펴 보았고 파일이 실제로 거기에 있습니다. 그 임시 디렉토리에 EXE를 놓으면 그것을 찾습니다. 매우 당혹 스럽습니다.

이것은 내가 .spec파일에 추가 한 것입니다

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

나는 그것들을 하위 폴더에 넣지 않았고 차이를 만들지 않았다고 덧붙여 야한다.

편집 : PyInstaller 업데이트로 인해 최신 답변이 올바른 것으로 표시되었습니다.


11
정말 고맙습니다! 여기에있는 줄 ( a.datas += ...)이 정말 도움이되었습니다. pyinstaller 문서는 사용에 대해 이야기 COLLECT하지만 사용할 때 파일을 바이너리에 넣지 못합니다--onefile
Igor Serebryany

@IgorSerebryany : 두 번째! 나는 똑같은 문제가 있었다.
Hubro

내가 사용한 경우 메뉴 표시 줄을 클릭 할 때 내 .exe 충돌
iacopo 2013

1
실행이 완료되면 임시 폴더가 사라지는 것을 고려하십시오. 그 안에 무엇이 있는지 확인하려면 프로그램 main
hithwen

내가 그 장소에서 본 것 같은 Tree () 구문을 사용하는 방법도 있습니까?
fatuhoku 2013 년

답변:


152

최신 버전의 PyInstaller는 env더 이상 변수를 설정하지 않으므로 Shish의 탁월한 답변 이 작동하지 않습니다. 이제 경로는 다음과 같이 설정됩니다 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를 python 2.7과 함께 사용하고 _MEIPASS2있으며 envs에는 없지만 sys._MEIPASS잘 작동하므로 +1. 나는 제안한다 :path = getattr(sys, '_MEIPASS', os.getcwd())
kbec 2013

2
+1. 감사합니다. 잠시 동안 _MEIPASS2 환경 변수를 사용하려고 시도했지만, 작동하는 것을 기억하기 때문에 여전히 환경 변수 일 때 코드를 작성했습니다. 최근에 다시 컴파일했을 때 갑자기 중지되었습니다.
Favil Orbedios

8
나는 AttributeError더 일반적인 대신 잡는 것이 좋습니다 Exception. sys 가져 오기가 누락되고 경로가 자동으로 os.path.abspath.
Aaron

문제를 해결하는 데 도움이 될 수 있습니다 .
Phillip

1
_MEIPASS가 설정되지 않은 경우 현재 작업 디렉토리를 사용하는 것은 잘못된 것입니다. 내 대답을 참조하십시오 .
Jonathon Reinhart

51

pyinstaller는 데이터를 임시 폴더에 압축 해제하고이 디렉토리 경로를 _MEIPASS2환경 변수 에 저장 합니다. _MEIPASS2압축 모드에서 디렉터리 를 가져 오고 압축 해제 (개발) 모드에서 로컬 디렉터리를 사용하려면 다음을 사용합니다.

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

산출:

# 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
어떻게, 언제, 어디서 사용합니까?
gseattle

4
PyInstaller로 컴파일하려는 .py 파일에서이 스크립트를 사용해야합니다. 이 코드 조각을 .spec 파일에 넣지 마십시오. 작동하지 않습니다. 일반적으로 입력하는 경로를로 대체하여 파일에 액세스합니다 resource_path("file_to_be_accessed.mp3"). 현재 버전의 PyInstaller에 대해 max '대답을 사용해야합니다.
Exeleration-G 2013

1
이 답변은 --one-file옵션 사용에만 해당 합니까?
fatuhoku

문제를 해결하는 데 도움이 될 수 있습니다 .
Phillip

_MEIPASS가 설정되지 않은 경우 현재 작업 디렉토리를 사용하는 것은 잘못된 것입니다. 내 대답을 참조하십시오 .
Jonathon Reinhart

30

다른 모든 답변 은 응용 프로그램이 PyInstalled가 아닌 경우 (즉, 설정 되지 않은 경우) 현재 작업 디렉토리 를 사용합니다 sys._MEIPASS. 스크립트가있는 디렉터리가 아닌 다른 디렉터리에서 애플리케이션을 실행할 수 없기 때문에 이는 잘못된 것입니다.

더 나은 솔루션 :

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)

감사합니다 Jon, 귀하의 기능이 오늘 문제를 해결하는 데 도움이되었습니다. 질문이 있습니다. 왜 일부는 _MEIPASS 대신 _MEIPASS2를 작성합니까? 전에 2를 추가하려고했지만 작동하지 않았습니다.
Ahmed AbdelKhalek

나는 os.env['_MEIPASS2'](OS 환경을 사용하는) 디렉토리를 얻는 오래된 방법 이라고 생각 합니다. AFAIK sys._MEIPASS는 현재 유일하게 올바른 방법입니다.
Jonathon Reinhart 2018 년

안녕하세요, 솔루션 resource_path()이 주 스크립트에 있을 때 제대로 작동합니다 . 대신 모듈로 작성 될 때 작동하도록하는 방법이 있습니까? 지금은 메인이 아닌 모듈이있는 폴더에서 리소스를 가져 오려고합니다.
Guimoute

1
@Guimoute는이 답변의 코드가 설계된대로 작동하는 것처럼 들립니다. 리소스를 제공하는 모듈로 지역화합니다 __file__. 모듈이 자체 범위 밖의 리소스에 액세스 할 수 있도록하려면 가져 오기 코드가 모듈이 사용할 경로를 제공하도록 구현해야합니다. 예를 들어 모듈이 "set_resource_location ()"호출을 importer 호출-이것이 pyinstaller를 사용하지 않을 때 작업하는 방법과 다르지 않다고 생각하지 마십시오.
barny

@barny 힌트 주셔서 감사합니다! 나는 그 라인을 따라 무언가를 시도 할 것입니다.
Guimoute 19.01.06

14

아마도 내가 한 단계를 놓쳤거나 뭔가 잘못했지만 위의 방법은 PyInstaller와 함께 데이터 파일을 하나의 exe 파일로 묶지 않았습니다. 내가 한 단계를 공유하겠습니다.

  1. 단계 : sys 및 os 모듈을 가져 와서 위의 방법 중 하나를 py 파일에 작성하십시오. 나는 둘 다 시도했다. 마지막은 다음과 같습니다.

    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. 단계 : 콘솔에 pyi-makespec file.py 를 작성하여 file.spec 파일을 만듭니다.

  3. 단계 : Open, file.spec with Notepad ++ to add the data files like below :

    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. 단계 : 위 단계를 따른 다음 사양 파일을 저장했습니다. 마침내 콘솔을 열고 pyinstaller file.spec (제 경우에는 file = Converter-GUI)을 작성합니다.

결론 : dist 폴더에는 여전히 하나 이상의 파일이 있습니다.

참고 : 저는 Python 3.5를 사용하고 있습니다.

편집 : 마지막으로 Jonathan Reinhart의 방법 으로 작동합니다 .

  1. 단계 : sys 및 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)
  2. 단계 : 파일 경로를 추가하여 위 함수를 호출합니다.

    image_path = resource_path("Converter-GUI.ico")
  3. 단계 : 코드에 경로가 필요한 위치에 함수를 호출하는 위의 변수를 작성하십시오. 제 경우에는 다음과 같습니다.

        self.window.iconbitmap(image_path)
  4. 단계 : Python 파일의 동일한 디렉토리에서 콘솔을 열고 아래와 같은 코드를 작성합니다.

        pyinstaller --onefile your_file.py
  5. 단계 : python 파일의 .spec 파일을 열고 a.datas 배열을 추가하고 3 단계에서 편집하기 전에 위에 제공된 exe 클래스에 아이콘을 추가합니다.
  6. 단계 : 경로 파일을 저장하고 종료합니다. spec 및 py 파일이 포함 된 폴더로 이동하십시오. 콘솔 창을 다시 열고 아래 명령을 입력하십시오.

        pyinstaller your_file.spec

6. 단계가 끝나면 하나의 파일을 사용할 수 있습니다.


감사합니다 @dilde! a.datas5 단계 의 배열이 문자열의 튜플을 취하는 것은 아닙니다 . 참조를 위해 pythonhosted.org/PyInstaller/spec-files.html#adding-data-files 를 참조하세요.
Ian Campbell

죄송합니다. 저의 영어가 약해서 메시지의 일부를 이해할 수 없습니다. 그 부분은 "아니 a.datas이 .... 것을" 당신이 쓰고 싶은나요 a.datas ... "라는 '주의 가 뭔가 잘못은 내가 a.datas 배열에 문자열을 추가하는 방법에 대해 쓴 것과인가?
dildeolupbiten

이런! 그것은해야한다 그 ... 참고 나중에 미안 오타에 대해. 귀하의 단계는 저에게 효과적이었습니다. :), 문서 나 다른 곳에서이 정보를 찾을 수 없었습니다.
Ian Campbell

8

제안 된대로 모든 경로 코드를 다시 작성하는 대신 작업 디렉토리를 변경했습니다.

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

코드 시작 부분에이 두 줄을 추가하기 만하면 나머지는 그대로 둘 수 있습니다.


2
아니요. 좋은 응용 프로그램은 작업 디렉토리를 거의 변경하지 않습니다. 더 나은 방법이 있습니다.
Jonathon Reinhart

3

허용되는 답변에 약간의 수정이 있습니다.

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가 설정되지 않은 경우 현재 작업 디렉토리를 사용하는 것은 잘못된 것입니다. 내 대답을 참조하십시오 .
Jonathon Reinhart

1

내가 wrt PyInstaller에서 본 가장 일반적인 불만 / 질문은 "내 코드가 번들에 확실히 포함 된 데이터 파일을 찾을 수 없습니다. 어디에 있습니까?"이며, 코드가 무엇인지, 어디에 있는지 쉽게 알 수 없습니다. 추출 된 코드가 임시 위치에 있고 종료시 제거되기 때문에 검색 중입니다. 코드의이 비트를 추가 참조 하여 onefile에 포함하고, @Jonathon 라인 하트의를 사용하여이되는 경우 어떤resource_path()

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

0

기존 답변이 혼란스럽고 문제가 어디에 있는지 파악하는 데 오랜 시간이 걸렸습니다. 여기 내가 찾은 모든 것의 모음집입니다.

내 앱을 실행할 때 오류가 발생합니다 Failed to execute script foo( foo.py기본 파일 인 경우). 이 문제를 해결하려면 PyInstaller를 실행하지 마십시오 --noconsole(또는 편집 main.spec하여 console=False=> console=True). 이를 통해 명령 줄에서 실행 파일을 실행하면 오류가 표시됩니다.

가장 먼저 확인해야 할 것은 추가 파일을 올바르게 패키징하고 있다는 것입니다. ('x', 'x')폴더 x를 포함 시키 려면 튜플을 추가해야합니다 .

충돌 후 확인을 클릭하지 마십시오. Windows를 사용하는 경우 모두 검색 을 사용할 수 있습니다 . 파일 중 하나를 찾습니다 (예 :) sword.png. 파일의 압축을 푼 임시 경로를 찾아야합니다 (예 :) C:\Users\ashes999\AppData\Local\Temp\_MEI157682\images\sword.png. 이 디렉토리를 찾아보고 모든 것이 포함되어 있는지 확인할 수 있습니다. 이 방법으로 찾을 수 없다면 main.exe.manifest(Windows) 또는 python35.dll(Python 3.5를 사용하는 경우 ) 와 같은 것을 찾으십시오 .

설치 프로그램에 모든 것이 포함되어있는 경우 다음으로 발생할 수있는 문제는 파일 I / O입니다. Python 코드는 임시 디렉터리가 아닌 실행 파일 디렉터리에서 파일을 찾습니다.

이 문제를 해결하기 위해이 질문에 대한 답변이 작동합니다. 개인적으로, 나는 그것들이 모두 작동하는 것을 발견했습니다. 기본 진입 점 파일에서 먼저 조건부로 디렉토리를 변경하고 다른 모든 것은 그대로 작동합니다.

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


1
죄송합니다. 그러나 디렉토리 변경은 정답이 아닙니다. 사용자가 응용 프로그램에 대한 경로를 제공하는 경우 현재 디렉터리에 상대적인 경로를 예상합니다. 그것을 변경하면 잘못된 것입니다.
Jonathon Reinhart 2017 년

0

임시 디렉토리가 아닌 실행 파일과 관련된 파일을 계속 넣으려는 경우 직접 복사해야합니다. 이것이 내가 끝내게 된 방법입니다.

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

DISTPATH ​​변수에 파일 시스템 복사를 수행하는 단계를 스펙 파일에 추가합니다.

도움이 되었기를 바랍니다.


0

나는이 문제를 오랫동안 ( 아주 오랫동안) 다루어 왔습니다. 거의 모든 소스를 검색했지만 머릿속에서 패턴이 나오지 않았습니다.

마지막으로 따라야 할 정확한 단계를 파악했다고 생각하고 공유하고 싶습니다.

내 답변은이 질문에 대한 다른 사람의 답변 정보를 사용합니다.

파이썬 프로젝트의 독립 실행 형 실행 파일을 만드는 방법.

project_folder가 있고 파일 트리가 다음과 같다고 가정합니다.

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

우선,의 당신이 당신의 경로에 대한 정의 가정 해 봅시다 sound/img/변수에 폴더 sound_dirimg_dir같은 다음과 같습니다 :

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

다음과 같이 변경해야합니다.

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

여기서, resource_path()스크립트 상단에 다음과 같이 정의됩니다.

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를 사용하는 경우 가상 환경 활성화,

아직 설치하지 않은 경우 pyinstaller를 설치하십시오 pip3 install pyinstaller.

실행 : pyi-makespec --onefile main.py컴파일 및 빌드 프로세스에 대한 사양 파일을 만듭니다.

그러면 파일 계층이 다음과 같이 변경됩니다.

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

Open (with an edior) main.spec:

그 위에 다음을 삽입하십시오.

added_files = [

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

]

그런 다음 줄 datas=[],datas=added_files,

작업에 대한 자세한 내용 main.spec여기 를 참조 하십시오.

운영 pyinstaller --onefile main.spec

그리고 모든입니다, 당신은 실행할 수 main있는 project_folder/dist그 폴더에 아무것도하지 않고, 어디서나. 해당 main파일 만 배포 할 수 있습니다 . 이제 진정한 독립형 .


@JonathonReinhart 당신이 아직 주위에 있다면, 나는 내 대답에 당신의 기능을 사용했다는 것을 알리고 싶었습니다.
muyustan

0

이미지 또는 사운드와 같은 추가 데이터 파일 추가 및 자체 연구 / 테스트에 대한 MaxThis post 의 훌륭한 답변을 사용하여 이러한 파일을 추가하는 가장 쉬운 방법이 무엇인지 알아 냈습니다.

당신이 살아있는 예제를보고 싶은 경우, 저장소 (repository)는 여기 GitHub의에.

참고 : 이것은 pyinstaller와 함께 --onefile또는 -F명령을 사용하여 컴파일하기위한 것입니다.

내 환경은 다음과 같습니다.


2 단계로 문제 해결

이 문제를 해결하려면 Pyinstaller에 응용 프로그램과 함께 "번들"되어야하는 추가 파일이 있음을 구체적으로 알려야합니다.

또한 '상대적'경로 를 사용해야 하므로 애플리케이션이 Python 스크립트 또는 고정 EXE로 실행될 때 제대로 실행될 수 있습니다.

우리는 상대 경로를 가질 수있는 함수가 필요합니다. Max Posted 함수를 사용하면 상대 경로를 쉽게 해결할 수 있습니다.

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)

위의 함수를 이와 같이 사용하여 앱이 스크립트 또는 고정 EXE로 실행될 때 애플리케이션 아이콘이 표시되도록합니다.

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

다음 단계는 컴파일 할 때 추가 파일을 찾을 위치를 Pyinstaller에 지시하여 응용 프로그램이 실행될 때 임시 디렉토리에 생성되도록하는 것입니다.

문서에 표시된 대로이 문제를 두 가지 방법으로 해결할 수 있지만 개인적으로 .spec 파일을 관리하는 것을 선호하므로 그렇게 할 것입니다.

먼저 .spec 파일이 있어야합니다. 제 경우에는 pyinstaller추가 인수 로 실행 하여 필요한 것을 만들 수 있었으며 여기에서 추가 인수를 찾을 수 있습니다 . 이 때문에 내 사양 파일이 귀하의 것과 약간 다를 수 있지만 중요한 부분을 설명하고 참조 용으로 모두 게시합니다.

added_files는 기본적으로 튜플의, 내 경우에는 내가 단 하나의 이미지를 추가 꿔 포함하는 목록입니다,하지만 당신은 사용의 또는 JPG의를 PNG, 여러 ICO의 추가 할 수 있습니다('app/img/*.ico', 'app/img')과 같이 또 다른 튜플을 만들 수 있습니다 당신을added_files = [ (), (), ()]여러 수입을 가지고

튜플의 첫 번째 부분은 추가 할 파일 또는 파일 유형과 파일 을 찾을 위치를 정의합니다. 이것을 CTRL + C로 생각하십시오.

튜플의 두 번째 부분은 Pyinstaller에게 'app / img /'경로를 만들고 .exe를 실행할 때 생성되는 임시 디렉터리에 상대적인 해당 디렉터리에 파일을 배치하도록 지시합니다. 이것을 CTRL + V로 생각하십시오.

에서a = Analysis([main...datas=added_files 원래는를 설정datas=[]했지만 가져 오기 목록을 가져 오기를 원하므로 사용자 정의 가져 오기를 전달합니다.

EXE에 대한 특정 아이콘을 원하지 않는 한이 작업을 수행 할 필요가 없습니다. 스펙 파일 하단에서 Pyinstaller에게 exe에 대한 내 애플리케이션 아이콘을 옵션으로 설정하도록 지시합니다 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로 컴파일

나는 매우 게으르다. 나는 내가해야하는 것보다 더 많은 것을 입력하는 것을 좋아하지 않는다. 클릭하기 만하면되는 .bat 파일을 만들었습니다. 이 작업을 수행 할 필요는 없습니다.이 코드는 명령 프롬프트 셸에서 실행됩니다.

.spec 파일에는 모든 컴파일 설정 및 인수 (일명 옵션)가 포함되어 있으므로 해당 .spec 파일을 Pyinstaller에 제공하면됩니다.

pyinstaller.exe "Process Killer.spec"

0

또 다른 해결책은 실행 파일이 저장된 디렉토리로 데이터 (파일 / 폴더)를 복사 (또는 이동)하는 런타임 후크를 만드는 것입니다. 후크는 앱 실행 직전에 거의 모든 작업을 수행 할 수있는 간단한 파이썬 파일입니다. 이를 설정하려면 --runtime-hook=my_hook.pypyinstaller 옵션을 사용해야합니다. 따라서 데이터가 이미지 폴더 인 경우 다음 명령을 실행해야합니다.

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

cp_images_hook.py는 다음과 같을 수 있습니다.

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.")

모든 실행 전에 이미지 폴더는 현재 디렉토리 (_MEIPASS 폴더에서)로 이동하므로 실행 파일은 항상 액세스 할 수 있습니다. 이렇게하면 프로젝트 코드를 수정할 필요가 없습니다.

두 번째 솔루션

런타임 후크 메커니즘을 활용하고 현재 디렉토리를 변경할 수 있습니다. 이는 일부 개발자에 따르면 좋은 방법은 아니지만 제대로 작동합니다.

후크 코드는 아래에서 찾을 수 있습니다.

import sys
import os

path = getattr(sys, '_MEIPASS', os.getcwd())   
os.chdir(path)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.