BetaRavener / uPyLoader

File transfer and communication tool for MicroPython boards
MIT License
354 stars 77 forks source link

Compile into a single exe? #15

Closed jdeltoft closed 7 years ago

jdeltoft commented 7 years ago

Have you thought about making this into a windows exe file instead of having to run main.py?

BetaRavener commented 7 years ago

I don't have experience with packing python applications to exe. Also there might be problem with PyQt, because it needs those large Qt dlls. I have worked on a c++ application in past that used Qt and had to pack most of the libraries with it, which increased the total size a lot.

However, I have recently used an application called FlatCAM, which also seems to be using PyQt and they managed to create Windows installer and have the app as exe file. Might be a source of inspiration for this.

jdeltoft commented 7 years ago

I'll check out if py2exe supports PyQt

jdeltoft commented 7 years ago

I tried out pyinstaller, and it was really easy with no reported errors, but then it failed trying to run because of PyQt5. I will look more into it, but this one seems pretty promising.

jdeltoft commented 7 years ago

I got pyinstaller to make this into a single main.exe. I had to uninstall and reinstall pyserial with version 3 instead of version 2 using pip, and I had to install PyQt5 with pip. I also then had to call out some PyQt5 stuff explicitly in the ".spec" file. I also installed the latest dev branch of pyinstaller just in case any fixes where there. Here is my current main.spec file right now that can at least produce a main.exe that runs. But it crashes for me when I tried to compile something. A lot of work still needed it looks like.

main.spec.txt

First install pyinstaller with "pip install pyinstaller". Then rename this file to main.spec. Then if your other libs are installed you should be able to run "pyinstaller main.spec" to create a ./dist/main.exe that runs and brings up the gui.

I think this one file (18MB) should be all you need then to run the program, but like I said, it still has crashes.

Bug reports like this one helped: https://github.com/pyinstaller/pyinstaller/issues/2402

BetaRavener commented 7 years ago

Nice, sounds like you put a lot of research into this, thanks a lot! I will try to build the executable and find out why the compilation is not working.

BetaRavener commented 7 years ago

Ok, seems that I've fixed it, had to pipe all outputs/inputs of the subprocess. Great work 👍 Now that I remember, the flashing utility is also using subprocess so I might have to fix it there too in next commit. Anyway it's working well. Interesting that my executable is much larger (28MB).. I have pushed it to the repository and we might place a download link pointing to it somewhere, so people won't have to clone repository and setup python environment anymore.

jdeltoft commented 7 years ago

Thanks for the updates. I downloaded your exe and unfortunately for me it still crashes on doing a compile for a single .py file. When you make your next commit, change one line in the .spec file so we can see the failures for now. Change the line with console to "console=True". Thanks again for jumping in here!

jdeltoft commented 7 years ago

Strangley, when I changed that line to console true for me and then rebuilt the uPyLoader.exe, and then tried the compile it worked?? Confused, since I didn't merge up your latest commit yet. I'll have to think about that.

BetaRavener commented 7 years ago

Fixed the flashing subproces (at least hope so, doesn't have board available to flash) and added icon for the application. The icon currently shows up only in explorer. The windows taskbar seems to require more mending: https://stackoverflow.com/questions/1551605/how-to-set-applications-taskbar-icon-in-windows-7/1552105#1552105 . In that post, the OP shows how to set icon for the application window and here is how to access the image in executable: https://stackoverflow.com/questions/9946760/add-image-to-spec-file-in-pyinstaller .

It will require some tinkering around to get it working but I think it can be done. Also the icon is just some quick sketch, I'll do something nicer in the future.

BetaRavener commented 7 years ago

@jdeltoft Setting console to True makes it work because then the subprocess implicitly maps its console IO to that console window. The problem is when the application has no console window, the subprocess doesn't know where to map these IO, so it causes OSError. Therefore, it is required to pipe all IOs when opening the subprocess.

I'm not sure why it still crashes for you, because I'm catching that exception now and it should create warning dialog with message, not crash. Try to delete your executable and rebuild it yourself, we can test the executable in repository later when it's working locally for everyone. Also be sure to checkout the master branch, I'm pushing those changes there instead of the FileList branch.

BetaRavener commented 7 years ago

Whelp, the pyinstaller complicated things somewhat. I realized that same as with application icon, it will be necessary to pack all other icons (indeed running the executable now, you can see that icons are missing, e.g. refresh next to port dropdown). So, packing them isn't problem, but their path need to be resolved properly once the application is running. This means wrapping all resource strings in a function, even those in scripts produced by PyQt builder. So, I decided to modify buildgui.py script to do this automatically, because doing that after each change to .ui files would be PITA. Anyway, just finishing and it seems to be working well, just let me know if you spot some missing icons or have any related problems.

BetaRavener commented 7 years ago

The executable is now working well for me. Can you try to use one from this repository? If it's not working, please try to create it yourself and report if that one is working. Thanks!

jdeltoft commented 7 years ago

Great! Downloading it now, will let you know shortly how my testing goes.

Nice icon! Love it! :+1:

jdeltoft commented 7 years ago

I'm testing on windows 7 64 bit just FYI.

Tested the following:

Thanks! Awesome job!!

jdeltoft commented 7 years ago

One thing I noticed while upmerging my jdeltoft-master branch to resolve the merge conflicts. The file I shared above has a hard coded path from my computer. Did you have to update that when you built your uPyLoader.exe that you uploaded?

pathex=['C:\Users\celtofj\My Documents\github\uPyLoader

BetaRavener commented 7 years ago

Well, it wouldn't be possible without you as I had no time to actually make it into executable. I just gave it some final touches, but this is your work :)

Regarding the config file, I guess it could be made hidden but I'm not sure how to make it cross-platform in an easy way (without detecting OS). Unix uses . as first character, Windows has attribute on the file. I think it's currently not worth the hassle. Glad that everything else works though. I'm using Windows 10 so that's at least 2 different systems tested. I can try and test it on my Linux machine later.

And about the path, I didn't even notice it until now :) I have been running the pyinstaller from main uPyLoader folder, so I guess that's why there was no issue. I will remove it from the spec file in another commit. I'm going to close this issue as it's probably done, but feel free to reopen or start a new one if needed.

jdeltoft commented 7 years ago

Yea, not a big deal on the hidden part. Just something I noticed. Actually, I can just mark it "hidden" myself if I want.

That's good you tested on windows 10. Of course you'll have to run pyinstaller on linux to make an exe that will run on linux, but I'm assuming you already knew that. ;-)

Yea, good to close. Not worried about the path other than wanted to make sure it didn't mess anything up.