Проблемы с компиляцией .py в .exe

#python #python-3.x #pyinstaller

Вопрос:

Я пытаюсь скомпилировать файл .py в файл .exe с помощью pyinstaller, но я всегда получаю это предупреждение в терминале:

 c:userscpuhvappdatalocalprogramspythonpython39libsite-packagessetuptoolsdistutils_patch.py:25: UserWarning: Distutils was imported before Setuptools. This u
sage is discouraged and may exhibit undesirable behaviors or errors. Please use Setuptools' objects directly or at least import Setuptools first.
  warnings.warn(
 

Когда я пытаюсь запустить файл .exe, я получаю окно с предупреждением с текстом: «Не удалось выполнить сценарий».

Кто-нибудь знает, как это исправить?

Комментарии:

1. можете ли вы поделиться сценарием, если это возможно, и выполнить команду создать exe с помощью программы установки open py

Ответ №1:

Я нашел для тебя решение. Один файл и все такое. Я оставляю свой предыдущий ответ, так как, хотя он и не идеален, он может быть кому-то полезен.

Следуйте инструкциям, приведенным здесь: https://github.com/AlJohri/docx2pdf/issues/5

pyinstaller не хватает скрипта для запуска docx2pdf.

сохранить hook-docx2pdf.py в Libsite-пакетыPyInstallerкрючки Скопируйте текст ниже в:

из PyInstaller.utils.крючки импортируют collect_all

hiddenimports = collect_all(‘docx2pdf’)

После этого мне пришлось выйти и перезапустить PyCharm, но это исправило все ошибки, связанные с проблемами импорта docx2pdf.

После этого я столкнулся со множеством ошибок, связанных с PyQt. В прошлом у меня были проблемы с PyQt и Pyinstaller, работающими вместе.

Однако, если вы понизите рейтинг с PyQt6 до PyQt5, все ваши проблемы будут решены. Затем просто измените свой список импорта на импорт из PyQt5.

Тогда беги pyinstaller --onefile -w main.py

Похоже, что Pyinstaller и PyQt6 еще не полностью совместимы.

Если это сработает, я был бы признателен, если бы вы отметили это как принятый ответ.

Ответ №2:

 import sys
import os
import comtypes.client
from pdf2docx import Converter
from docx2pdf import convert
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QToolTip, QFileDialog, QLineEdit, QLabel
from PyQt6.QtGui import QIcon, QFont
from pathlib import Path


home_directory = str(Path.home()).replace("/", "\")


def name(file):
    path = file
    i = 1
    while os.path.exists(path):
        path = file
        path  = " "   str(i)
        i  = 1
    return path


class MainGui(QWidget):
    def __init__(self):
        super().__init__()

        self.row1 = 50
        self.row2 = 100
        self.row3 = 175
        self.row4 = 260

        self.button_font = QFont('Verdana', 10)
        self.line = QLineEdit(self)
        self.browse = QPushButton("Durchsuchen", self)
        self.selected_files_count = QLabel("0 Elemente ausgewählt", self)
        self.docx_files = []
        self.pdf_files = []
        self.init_me()

    def init_me(self):
        font = QFont('Verdana', 8)
        font.setBold(True)
        QToolTip.setFont(font)

        pdf_to_docx_button = QPushButton('PDF Dateien auswählen', self)
        pdf_to_docx_button.setFont(self.button_font)
        pdf_to_docx_button.setToolTip('öffen Sie einen Datei-Dialog, um Dateien auszuwählen')
        pdf_to_docx_button.move(50, self.row1)
        pdf_to_docx_button.setFixedWidth(200)
        pdf_to_docx_button.setFixedHeight(35)
        pdf_to_docx_button.clicked.connect(self.pdf_to_docx_button_pressed)

        docx_to_pdf_button = QPushButton('DOCX Dateien auswählen', self)
        docx_to_pdf_button.setFont(self.button_font)
        docx_to_pdf_button.setToolTip('öffen Sie einen Datei-Dialog, um Dateien auszuwählen')
        docx_to_pdf_button.move(300, self.row1)
        docx_to_pdf_button.setFixedWidth(200)
        docx_to_pdf_button.setFixedHeight(35)
        docx_to_pdf_button.clicked.connect(self.docx_to_pdf_button_pressed)

        self.line.move(50, self.row3)
        self.line.setFixedWidth(320)
        self.line.setFixedHeight(30)
        self.line.setFont(self.button_font)
        self.line.setText(home_directory)

        self.browse.move(390, self.row3)
        self.browse.setFont(self.button_font)
        self.browse.setFixedWidth(110)
        self.browse.setFixedHeight(30)
        self.browse.setToolTip('öffen Sie einen Datei-Dialog, um den Ausgabe-Ordner auszuwählen')
        self.browse.clicked.connect(self.browse_button_pressed)

        convert_button = QPushButton('Konvertieren', self)
        convert_button.move(190, self.row4)
        convert_button.setFixedWidth(170)
        convert_button.setFixedHeight(50)
        convert_button.setFont(self.button_font)
        convert_button.clicked.connect(self.convert)

        self.selected_files_count.move(200, self.row2)
        self.selected_files_count.setFont(self.button_font)
        self.selected_files_count.setFixedSize(200, 50)

        self.move(50, 50)
        self.setFixedSize(550, 400)
        self.setWindowTitle("Konverter")
        self.setWindowIcon(QIcon(r"icon.png"))
        self.show()

    def pdf_to_docx_button_pressed(self):
        fd = QFileDialog()
        fd.setAcceptMode(QFileDialog.AcceptMode.AcceptOpen)
        path = fd.getOpenFileNames(self, "PDF Dateien öffnen", home_directory, "PDF (*.pdf)")
        fd.close()
        print(len(path[0]))
        if len(path[0]) > 0:
            self.pdf_files.extend(path[0])
            print(True)
            self.update_label()

    def docx_to_pdf_button_pressed(self):
        fd = QFileDialog()
        fd.setAcceptMode(QFileDialog.AcceptMode.AcceptOpen)
        path = fd.getOpenFileNames(self, "Docx Dateien öffnen", home_directory, "Word-Dokument ("
                                                                                                  "*.docx)")
        fd.close()
        if len(path[0]) > 0:
            self.docx_files.extend(path[0])
            self.update_label()

    def convert(self):
        directory = self.line.text()
        if not os.path.exists(directory):
            return
        if not os.path.isdir(directory):
            return
        for file in self.pdf_files:
            docx_file = name(directory   "/"   os.path.basename(file).replace(".pdf", ".docx"))
            convert_pdf_to_docx(file, docx_file)
            update_docx(docx_file)
        for file in self.docx_files:
            convert_docx_to_pdf(file, name(directory   "/"   os.path.basename(file).replace(".docx", ".pdf")))
        self.docx_files = []
        self.pdf_files = []

    def browse_button_pressed(self):
        fd = QFileDialog()
        fd.setAcceptMode(QFileDialog.AcceptMode.AcceptSave)
        path = fd.getExistingDirectory(self, "Ausgabeordner auswählen", home_directory)
        if path is not None and not len(path) <= 0:
            self.line.setText(path)

    def update_label(self):
        count = len(self.pdf_files)   len(self.docx_files)
        if count != 1:
            self.selected_files_count.setText(str(count)   " Elemente ausgewählt")
        else:
            self.selected_files_count.setText("ein Element ausgewählt")


def convert_pdf_to_docx(pdf_file, docx_file):
    cv = Converter(pdf_file)
    cv.convert(docx_file, start=0, end=None)
    cv.close()


def convert_docx_to_pdf(docx_file, pdf_file):
    convert(docx_file, pdf_file)


def update_docx(file):
    docx_format_name = 16
    file_in = os.path.abspath(file)
    file_out = file_in.replace(".docx", "2.docx")
    word_application = comtypes.client.CreateObject('word.Application')
    if word_application is not None:
        doc = word_application.Documents.Open(file_in)
        doc.SaveAs(file_out, FileFormat=docx_format_name)
        doc.Close()
        word_application.Quit()
        os.remove(file_in)
        os.rename(file_out, file_in)


app = QApplication(sys.argv)

w = MainGui()

sys.exit(app.exec())
 

Это мой код.

Команда такова:

 pyinstaller --noconfirm --onefile --windowed  "C:/Users/cpuhv/Documents/Projekte/Python/Python Test/PDFConverter.py"
 

Ответ №3:

Так что вчера у меня были похожие проблемы. У меня есть обходной путь, который позволит программе запускаться, но не в виде одного файла. Это также сделает папку, к сожалению, большой, так как она будет включать все ваши виртуальные пакеты env. Я надеюсь, что кто-то другой сможет дать вам лучший ответ.

Во-первых, не используйте —windowed при отладке. Опустите —windowed, а затем запустите файл .exe с помощью командной строки. Это покажет вам ошибки. В этом случае:

   Traceback (most recent call last):
  File "main.py", line 6, in <module>
  File "PyInstallerloaderpyimod03_importers.py", line 531, in exec_module
  File "docx2pdf__init__.py", line 13, in <module>
  File "importlibmetadata.py", line 551, in version
  File "importlibmetadata.py", line 524, in distribution
  File "importlibmetadata.py", line 187, in from_name
importlib.metadata.PackageNotFoundError: docx2pdf
[6860] Failed to execute script main
 

Мы видим ошибку импорта, поскольку Pyinstaller не учитывает импорт второго уровня. В этом случае я считаю, что docx2pdf имеет свой собственный список импорта. Посмотрите на крючки и ошибки импорта, есть много решений — однако лично я не смог добиться результатов с помощью решений, которые я прочитал.

Поэтому мое альтернативное решение «бандаж» для вас требует, чтобы вы использовали файл .spec. Pyinstaller --noconfirm main.py Далее вам нужно отредактировать файл main.spec, созданный в вашем рабочем каталоге. добавьте папку «Пакеты сайта» в данные, чтобы она выглядела так:

 datas=[('C:\PathToProjectFolder\venv\Lib\site-packages', '.')]
 

И отредактируйте строку консоли в файле .spec следующим образом: console=False (скрывает консоль при нажатии на файл .exe)

С обновленным файлом .spec мы можем снова запустить Pyinstaller, на этот раз введя:

 pyinstaller --noconfirm main.spec
 

обратите внимание на main.spec, а не main.py.

Файл .exe в папке dist должен запуститься сейчас. Удачи в поиске лучшего решения, которое не сделает вашу папку непомерно большой.

Комментарии:

1. Там написано: «Не удалось выполнить скрипт PDFConverter».

2. @Red_Head_CPU Я просто снова следовал своим собственным инструкциям с нуля в новом проекте, и это сработало для меня. Убедитесь, что в данных вы добавляете путь, как я упоминал выше. Вы должны указывать весь путь в venv, вплоть до пакетов сайта. Убедитесь, что вы используете pyinstaller —noconfirm main.SPEC. Вы будете знать, что правильно добавили данные, если ваша конечная папка dist заполнена другими папками для всех модулей python, используемых в вашем проекте. Наконец, если это не удастся. Перестройте новую среду проекта с помощью нового venv с нуля.

Ответ №4:

У меня была точно такая же проблема с правильной компиляцией PyQt6 с помощью pyinstaller. Я обнаружил, что проблема в том, что pyinstaller не копирует все необходимые файлы PyQt6 при создании файла .exe.

Что мне помогло, так это добавить всю папку PyQt6, используя флаг» --add-data «.

Итак, в конечном итоге у вас есть:

 pyinstaller --noconfirm --onefile --windowed  "C:/Users/cpuhv/Documents/Projekte/Python/Python Test/PDFConverter.py" --add-data "PYTHON_DIRECTORY/Lib/site-packages/PyQt6;PyQt6"
 

Конечно, вам нужно заменить « PYTHON_DIRECTORY » путем к вашему каталогу Python. Если вы используете виртуальную среду, то укажите путь к папке python « Lib » в вашем venv.

Хотя выполнение вышеперечисленных действий может создать дублирующуюся проблему, которую вам необходимо решить в созданном файле .spec. Если вы попытаетесь запустить приложение Qt и получите сообщение об ошибке в строке « the file already exists » для QtCore.pyd, QtGui.pyd and QtWidgets.pyd , не переживайте. Просто добавьте приведенный ниже код после « Analysis » части созданного вами файла .spec:

 for d in a.datas:
    if 'QtCore.pyd' in d[0]:
        a.datas.remove(d)
        break

for d in a.datas:
    if 'QtGui.pyd' in d[0]:
        a.datas.remove(d)
        break

for d in a.datas:
    if 'QtWidgets.pyd' in d[0]:
        a.datas.remove(d)
        break
 

Что делает приведенный выше код, так это удаляет эти три файла из папки PyQt6 в» datas «, поскольку эти файлы уже существуют в папке, созданной pyinstaller.

Когда вы закончите с этим, запустите сборку снова, используя « pyinstaller somefile.spec » и вуаля.

Надеюсь, это кому-то поможет, если вышеперечисленные решения также не сработали для вас