Почему добавленный в сборку исполняемый файл не может быть найден в приложении, скомпилированном с помощью Pyinstaller?

  • 16 августа 2023 г. 10:16
Ответы на вопрос 3
Возможно, причина, по которой добавленный в сборку исполняемый файл не может быть найден, - в неправильном пути к исполняемому файлу.

PyInstaller создает папку "dist" в каталоге проекта после сборки, в которой содержится собранный файл приложения. Однако, добавленные в сборку файлы хранятся внутри exe-файла, и при запуске exe-файла они извлекаются во временную папку и выполняются из нее.

При использовании команды `subprocess.Popen(("./ffmpeg.exe", …))` программа пытается найти `ffmpeg.exe` в текущей рабочей директории, а не во временной папке, где он был извлечен.

Чтобы исправить эту проблему, вы можете использовать `sys._MEIPASS`, чтобы получить путь к исполняемому файлу во время выполнения. Следующий код позволит правильно получить путь к `ffmpeg.exe`:

```python
import os
import subprocess
import sys

def resource_path(relative_path):
    """ Получение абсолютного пути к файлу, включенному в сборку """
    if hasattr(sys, "_MEIPASS"):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(relative_path)

ffmpeg_path = resource_path("ffmpeg.exe")
subprocess.Popen((ffmpeg_path, ...))
```

Обратите внимание, что `resource_path` - это вспомогательная функция, которая возвращает корректный путь к файлу, включенному в сборку, используя `sys._MEIPASS` в случае, если он доступен, или относительный путь в противном случае. Вы можете использовать эту функцию для получения абсолютного пути к любому файлу, включенному в сборку, не только к `ffmpeg.exe`.
subprocess.Popen(("./ffmpeg.exe", ...))


Ты используешь subprocess.Popen команду, чтобы запустить файл ffmpeg.exe. Однако, стоит помнить, что текущий каталог, где расположен скрипт, может не совпадать с каталогом, где расположен ffmpeg.exe. Вместо этого, лучше использовать абсолютный путь к файлу для избежания проблем. 

Таким образом, я рекомендую прочитать про относительный и абсолютный путь, чтобы получить лучшее понимание. Вот пример кода из документации, который позволяет получить абсолютный путь к текущему каталогу:

import sys
from pathlib import Path

if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):  
    # Если приложение запущено из пакета pyinstaller
    TEMP_DIR = Path(sys._MEIPASS).resolve()  
else:  
    # Если приложение не запущено из пакета pyinstaller
    TEMP_DIR = Path(sys.argv[0]).parent.resolve()  
# resolve() преобразует путь в абсолютный, чтобы избежать проблем при изменении текущего каталога
ffmpeg_path = str(TEMP_DIR / "ffmpeg.exe")  
ffmpeg = subprocess.Popen((ffmpeg_path, ...))
Похожие вопросы