#python #pyinstaller #linear-programming #cvxpy #coin-or-cbc
#python #pyinstaller #линейное программирование #cvxpy #монета или cbc
Вопрос:
Я пытаюсь собрать exe из скрипта python, чтобы решить проблему LP, используя cvxpy и CBC (через cylp) с помощью pyinstaller.
Код выглядит следующим образом:
import numpy as np
import cvxpy as cp
if __name__ == "__main__":
A = np.array([[2, 0, 0],
[1, 0, 2],
[0, 3, 1]])
b = np.array([4, 8, 6])
c = np.array([3, 4, 2])
# Define and solve the problem.
x = cp.Variable(3)
prob = cp.Problem(cp.Maximize(c.T @ x),
[A @ x <= b, x >= 0])
prob.solve(solver=cp.CBC)
print(f"solver: {prob.solver_stats.solver_name}")
# Print result.
print("The optimal value is", prob.value)
print("A solution x is")
print(x.value)
это корректно работает с интерпретатором python
> python .LP.py
solver: CBC
The optimal value is 16.0
A solution x is
[2. 1. 3.]
но exe, созданный pyinstaller, выдает ошибку
> pyinstaller .LP.spec
> .distLP.exe
Traceback (most recent call last):
File "LP.py", line 15, in <module>
prob.solve(solver=cp.CBC)
File "cvxpyproblemsproblem.py", line 396, in solve
File "cvxpyproblemsproblem.py", line 745, in _solve
File "cvxpyproblemsproblem.py", line 500, in get_problem_data
File "cvxpyproblemsproblem.py", line 651, in _construct_chain
File "cvxpyproblemsproblem.py", line 576, in _find_candidate_solvers
cvxpy.error.SolverError: The solver CBC is not installed.
[18960] Failed to execute script LP
Есть ли способ это исправить?
Я не могу избежать использования CBC, потому что на самом деле я хочу сделать, это создать exe, решающий задачу программирования со смешанным целым числом.
Моя среда:
numpy: 1.19.1
cvxpy: 1.1.4
cylp: 0.91.0
PyInstaller: 4.0
Python: 3.7.9
Платформа: Windows 10 v1909 64bit
Мой файл спецификации (созданный pyinstaller .LP.py -F
и мной модифицированный datas
):
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['LP.py'],
pathex=['C:\Users\aaa\Desktop\LP'],
binaries=[],
datas=[
('C:\Users\aaa\AppData\Local\Programs\Python\Python37\Lib\site-packages\cylp\*',
'.\cylp\')],
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='LP',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True)
Ответ №1:
Я сталкиваюсь с той же проблемой. Я попробовал обе следующие команды для сборки с тем же результатом:
pyinstaller name_of_my_package.py
pyinstaller --hidden-imports=cylp name_of_my_package.py
Но я все еще получаю ту же ошибку. Поскольку я создаю свой с несколькими файлами, я могу просто зайти в каталог dist / name_of_my_package / cylp /, и я вижу, что папка модуля cylp существует, но в этом каталоге есть только подпапка cy. Когда я удаляю dist / name_of_my_package / cylp / cy / из сборки и копирую содержимое моей папки cylp непосредственно из моей виртуальной среды python в dist/name_of_my_package / cylp /, мой exe работает. Но вы можете сделать это, только если вы не создаете с флагом —onefile.
Когда я закончу, я увижу следующую структуру папок:
dist/name_of_my_package/cylp/
|--cpp/
|--<a bunch of stuff in here>
|--cy/
|--<a bunch of stuff in here>
|--py
|--<a bunch of stuff in here>
|--__init__.py
|--VERSION
Исходная структура папок, созданная pyinstaller, выглядит только так:
dist/name_of_my_package/cylp/
|--cy/
|--<a bunch of stuff in here>
Похоже, что pyinstaller знает, как получить пакет cylp, но он не копирует все необходимые фрагменты. Я не уверен, каков реальный ответ здесь, но этот обходной путь работает для меня на данный момент. Надеюсь, кто-нибудь может указать нам правильный ответ.
Ответ №2:
Согласно документации, параметр «—add-data» или «Analysis / datas» в первой строке равен «относительно местоположения файла спецификации».
pyinstaller читает документ, используя файл данных из модуля
Я использовал строку консоли в Windows (двойные кавычки и разделитель точкой с запятой), чтобы добавить весь каталог cpp и файл ВЕРСИИ (больше ничего не нужно).
pyinstaller —add-data «cylp cpp; cylp cpp» —add-data «cylp VERSION; cylp» LP.py
Добавьте -F, если вы хотите сборку «onefile».
Поскольку путь к первой строке является относительным, сначала вам нужно скопировать всю папку cylp package-site из исходного каталога python в каталог LP.py
PS: Это мой первый ответ в Stackoverflow!