Python: исключая модули Pyinstaller

Я начал использовать Pyinstaller над Py2Exe. Однако я довольно быстро столкнулся с проблемой. Как я могу исключить модули, которые мне не нужны, и как просмотреть те, которые входят в один исполняемый файл?

Я могу удалить некоторые файлы pyd и dll из папки DLL в моей установке на Python, поэтому Pyinstaller не найдет и, следовательно, не включит их. Я действительно не хочу делать это со всеми модулями, так как это будет довольно сложно.

Я попытался отредактировать файл спецификации, который делает Pyinstaller.

a.binaries - [('ssl','pydoc',)],

Но размер файла остался прежним, поэтому я пришел к выводу, что это не сработало.

Итак, как я могу увидеть, какие модули содержат Pyinstaller, и как я могу исключить те, которые мне не нужны?

Ответ 1

Просто подытожим варианты здесь, когда я их использую.

PyInstaller TOC - есть, как говорится в документации:

A TOC представляет собой список кортежей формы (имя, путь, TypeCode). На самом деле это упорядоченный набор, а не список. TOC не содержит дубликаты, где уникальность основана только на имени.

В других словах просто:

a_toc = [('uname1','/path/info','BINARY'),('uname2','/path/to','EXTENSION')...]

Итак, в вашем файле .spec - после того, как вы получите результаты анализа script, вы можете дополнительно изменить соответствующий TOC:

  • Для определенных файлов/модулей используйте операции разности (-) и пересечения (+) для изменения TOC. *

  • Для добавления/удаления списков файлов/модулей итерации по TOC и сравнения с кодом соответствия шаблонов.

(* В стороне, для разницы в работе, кажется, вы должны явно использовать TOC() и отметить, что, поскольку это только имя, которое однозначно определяет элемент набора, вам нужно только указать, что - следовательно ('sqlite3', None, None) и т.д.)

Иллюстративный пример (взятый из файла .spec) находится ниже, где - для лучшего или худшего - я удаляю все ссылки на scipy, IPython и zmq; удалить конкретные sqlite, tcl/tk и ssl.DLL; вставить отсутствующий opencv.DLL; и, наконец, удалите все папки данных, найденные отдельно от matplotlib...

Будет ли возникающий в результате Pyinstaller.exe работать, когда файл .pyc пытается загрузить ожидаемый .DLL является спорным :-/

# Manually remove entire packages...

a.binaries = [x for x in a.binaries if not x[0].startswith("scipy")]

a.binaries = [x for x in a.binaries if not x[0].startswith("IPython")]

a.binaries = [x for x in a.binaries if not x[0].startswith("zmq")]

# Target remove specific ones...

a.binaries = a.binaries - TOC([
 ('sqlite3.dll', None, None),
 ('tcl85.dll', None, None),
 ('tk85.dll', None, None),
 ('_sqlite3', None, None),
 ('_ssl', None, None),
 ('_tkinter', None, None)])

# Add a single missing dll...

a.binaries = a.binaries + [
  ('opencv_ffmpeg245_64.dll', 'C:\\Python27\\opencv_ffmpeg245_64.dll', 'BINARY')]

# Delete everything bar matplotlib data...

a.datas = [x for x in a.datas if
 os.path.dirname(x[1]).startswith("C:\\Python27\\Lib\\site-packages\\matplotlib")]

Ответ 2

Вы можете манипулировать списками, создаваемыми классом Analysis, используя Python. Обратите внимание, что они находятся в формате TI PyInstaller.

a = Analysis(...)
...
# exclude anything from the Windows system dir       
a.binaries = [x for x in a.binaries if not 
              os.path.dirname(x[1]).startswith("C:\\Windows\\system32")]

Ответ 3

Хотя могут быть даны лучшие решения, но есть еще один метод: Вы можете использовать атрибут "--exclude-module" с командой "pyinstaller", но этот метод достаточно длинный, когда вам нужно исключить много модулей.

Чтобы упростить работу, вы можете написать файл пакетного скрипта со всеми библиотеками, которые стоит пропустить, и использовать его снова и снова.

Примерно так:

@echo off

pyinstaller --onefile a.py --exclude-module matplotlib ^
                           --exclude-module scipy ^
                           --exclude-module setuptools ^
                           --exclude-module hook ^
                           --exclude-module distutils ^
                           --exclude-module site ^
                           --exclude-module hooks ^
                           --exclude-module tornado ^
                           --exclude-module PIL ^
                           --exclude-module PyQt4 ^
                           --exclude-module PyQt5 ^
                           --exclude-module pydoc ^
                           --exclude-module pythoncom ^
                           --exclude-module pytz ^
                           --exclude-module pywintypes ^
                           --exclude-module sqlite3 ^
                           --exclude-module pyz ^
                           --exclude-module pandas ^
                           --exclude-module sklearn ^
                           --exclude-module scapy ^
                           --exclude-module scrapy ^
                           --exclude-module sympy ^
                           --exclude-module kivy ^
                           --exclude-module pyramid ^
                           --exclude-module opencv ^
                           --exclude-module tensorflow ^
                           --exclude-module pipenv ^
                           --exclude-module pattern ^
                           --exclude-module mechanize ^
                           --exclude-module beautifulsoup4 ^
                           --exclude-module requests ^
                           --exclude-module wxPython ^
                           --exclude-module pygi ^
                           --exclude-module pillow ^
                           --exclude-module pygame ^
                           --exclude-module pyglet ^
                           --exclude-module flask ^
                           --exclude-module django ^
                           --exclude-module pylint ^
                           --exclude-module pytube ^
                           --exclude-module odfpy ^
                           --exclude-module mccabe ^
                           --exclude-module pilkit ^
                           --exclude-module six ^
                           --exclude-module wrapt ^
                           --exclude-module astroid ^
                           --exclude-module isort

Или вы всегда можете использовать новую установку Python, просто измените путь новой установки Python во время установки.

Ответ 4

НАЙТИ ОТВЕТ СЕБЯ

Я видел много подобных вопросов, но никто не учит вас, как отлаживать самостоятельно.

Документ Pyinstaller может быть полезен для начинающих, но как только вам нужно больше...

лично я думаю, что документация pyinstaller не дружелюбна (слишком мало примеров) и не имеет обновлений.

Например, документ показывает версию pyinstaller 3.2. (3.5 доступно уже сейчас (2019/10/5))

Я хочу сказать, что вы должны найти ответ из исходного кода

НАЧАТЬ ПУТЬ

  • создайте файл сценария (например, run_pyinstaller.py), как показано ниже:
# run_pyinstaller.py

from PyInstaller.__main__ import run
run()
  • перед запуском этого скрипта вы можете назначить параметры, например "--clean your.spec"

  • установите точку останова на {env_path}/Lib/site-packages/PyInstaller/building/build_main.py -> def build(...) ... -> exec(code, spec_namespace), как показано ниже:

    примечание: Если вы не используете виртуальную среду, фактический путь должен быть {Python}/Lib/site-packages/PyInstaller/building/build_main.py

enter image description here

  • наконец, вы бежите сюда и нажимаете кнопку перехода в. Вы попадете в файл .spec

тогда вы можете посмотреть любые переменные, которые вас интересуют.

Кроме того, вы узнаете больше о pyinstaller.exe на самом деле делать.

например, вы узнаете, что класс оглавления наследуется от списка, и видите больше подробностей, чем документ из PyInstaller.building.datastruct

enter image description here

в конце концов, вы можете использовать любой способ Python для установки a.binaries и a.datas, который вы действительно хотели

ОБЪЕДИНЕННЫЕ ФАЙЛЫ

from PyInstaller.building.datastruct import TOC, Tree
from PyInstaller.building.build_main import Analysis
from PyInstaller.building.api import EXE, PYZ, COLLECT, PKG, MERGE