coin-or / python-mip

Python-MIP: collection of Python tools for the modeling and solution of Mixed-Integer Linear programs
Eclipse Public License 2.0
530 stars 92 forks source link

PyInstaller with mip "NameError: name 'cbclib' is not define" #198

Open simontt19 opened 3 years ago

simontt19 commented 3 years ago

Describe the bug I am writing a program that solve MIP and it works well when I directly run the code. But after I use pyinstaller to pack my code into an executable file and then when I run that file this error comes out("NameError: name 'cbclib' is not define").

To Reproduce The whole logic is complicated, so I only extract the relevant one.

  1. The script as below
    
    from mip import Model
    import tkinter as tk
    import sys
    def run():
    m = Model("load_planing") 
    r3 = str(m)
    r3_label.configure(text=r3)   

if name == "main": window = tk.Tk() window.title('Multi-SOC Optimizer') window.geometry('640x480') window.configure(background='white') calculate_btn = tk.Button(window, text='Start!',command=run) calculate_btn.pack(side=tk.TOP) r3_label = tk.Label(window) r3_label.pack(side=tk.TOP) window.mainloop() sys.exit()



2. Directly run the script on python is fine.
<img width="470" alt="debug_on_python" src="https://user-images.githubusercontent.com/13747773/124605260-4e03c100-de9e-11eb-8132-ccc34bb65f86.png">

3. Use pyinstaller to pack the logic. `pyinstaller -F -n mip_debug mip_debug.py`

4. Run the exe file after packed. => error
<img width="893" alt="debug_pyinstaller" src="https://user-images.githubusercontent.com/13747773/124605265-4f34ee00-de9e-11eb-99ec-dd0e74fd7d8b.png">

**Expected behavior**
Running the exe file's outcome should be same as directly run on python. 

**Desktop (please complete the following information):**
 - Operating System, version: 64-bit operating system, win10
 - Python version:3.8.3
 - Python-MIP version (we recommend you to test with the latest version): 1.13.0
nickpgill commented 2 years ago

I have the same error! Did you manage to fix it?

labaude commented 2 years ago

Same here with slightly different versions. Any resolution?

rschwarz commented 2 years ago

This is not actually a bug with this library. Rather, you need to specify that the required .dll file should be bundled with pyinstaller by using an --add-binary argument.

sebheger commented 2 years ago

@nickpgill @labaude @simontt19 Does the comment of @rschwarz fixes your problem?

nickpgill commented 2 years ago

Sorry for the delay in replying... I tried to make use of the suggestion from @rschwarz but I was not able to figure out how to use the --add-binary argument. If you can give me a clue here, then I will follow this up and see if I can make it work...

On Tue, 5 Apr 2022 at 20:39, Sebastian Heger @.***> wrote:

@nickpgill https://github.com/nickpgill @labaude https://github.com/labaude @simontt19 https://github.com/simontt19 Does the comment of @rschwarz https://github.com/rschwarz fixes your problem?

— Reply to this email directly, view it on GitHub https://github.com/coin-or/python-mip/issues/198#issuecomment-1089243562, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIC6SVOBT67BVJGHBVBGUXDVDSJHNANCNFSM474RQ6ZQ . You are receiving this because you were mentioned.Message ID: @.***>

rschwarz commented 2 years ago

I have not tried it with python-mip and Cbc, but here's how I called pyinstaller (on Windows) for a past project that used PySCIPOpt:

pyinstaller --onefile ^
            --add-binary "%SCIPOPTDIR%\bin\libscip.dll;." ^
            --add-binary "%SCIPOPTDIR%\bin\tbb.dll;." ^
            --windowed ^
            mypackage/myapp.py

where SCIPOPTDIR was previously defined via set SCIPOPTDIR=C:\Program Files\SCIPOptSuite 7.0.2. The result was a portable .exe that included the two relevant .dlls.

I'm no longer sure what the ;. suffix after the .dll path means :disappointed:

nickpgill commented 2 years ago

Thanks Robert, I appreciate your help with this. I'll see if I can make this work! Nick

On Mon, 25 Apr 2022 at 09:36, Robert Schwarz @.***> wrote:

I have not tried it with python-mip and Cbc, but here's how I called pyinstaller (on Windows) for a past project that used PySCIPOpt:

pyinstaller --onefile ^

        --add-binary "%SCIPOPTDIR%\bin\libscip.dll;." ^

        --add-binary "%SCIPOPTDIR%\bin\tbb.dll;." ^

        --windowed ^

        mypackage/myapp.py

where SCIPOPTDIR was previously defined via set SCIPOPTDIR=C:\Program Files\SCIPOptSuite 7.0.2. The result was a portable .exe that included the two relevant .dlls.

I'm no longer sure what the ;. suffix after the .dll path means 😞

— Reply to this email directly, view it on GitHub https://github.com/coin-or/python-mip/issues/198#issuecomment-1108255030, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIC6SVLCY4DHLWQQ5JZ32ZLVGZKRPANCNFSM474RQ6ZQ . You are receiving this because you were mentioned.Message ID: @.***>

sebheger commented 2 years ago

@nickpgill Will you share some insights with us so that I can see if there is some issue on python-mip side or that I can move it to the discussion section. Otherwise, I will close this issue.

zanghyu commented 1 year ago

you can write a hook-mip.py file there in a folder named hooks (create a folder hooks and touch a file hooks/hook-mip.py), and the code of hook-mip.py is:

from PyInstaller.utils.hooks import collect_all  
def hook(hook_api):  
    packages = ['mip']  
    for package in packages:  
        datas, binaries, hiddenimports = collect_all(package)  
        hook_api.add_datas(datas)  
        hook_api.add_binaries(binaries)
        hook_api.add_imports(*hiddenimports)

then, you can use pyinstaller as: pyinstaller -D xxx.py --additional-hooks-dir=./hooks/, then it will work.