daspartho / SpotiByeAds

Skip spotify ads by automatically restarting application when ad plays
GNU General Public License v3.0
285 stars 41 forks source link

Prebuilt executables #42

Open atridey opened 3 years ago

atridey commented 3 years ago

I think we should make a separate thread since this is a common request. We have a way to use py2app for Mac, but my attempts with pyinstaller and cxfreeze on windows have been unsuccessful. Has anyone else built outside of Mac?

AnonymouX47 commented 3 years ago

At the moment, I'm not sure how workable this is for Windows.

I tried PyInstaller with no success... i'll elaborate more soon.

I think the best option for now is for the user to have python installed, install the dependencies and run the script directly. I sincerly think the installation steps are easy enough to follow.

atridey commented 3 years ago

Have you been getting the same error as I have? I was getting import errors so it kept trying to download off of requirements.txt (which didn't exist in the build directory). Once I added requirements.txt, it downloaded, but still had an import error. Commenting out the code that downloads just showed an import error again. Switching from pyinstaller to cxfreeze did nothing.

I too believe it's easy to install with Python, but prebuilt executables are even easier.

AnonymouX47 commented 3 years ago

I tried PyInstaller (using the --onefile option) and encountered an ImportError. I should note that the 3rd-party libraries were also packaged along.

The import error occured from the pynput library:

Traceback (most recent call last):
  File "main.py", line 4, in <module>
    from pynput.keyboard import Key, Controller
  File "PyInstaller\loader\pyimod03_importers.py", line 540, in exec_module
  File "pynput\__init__.py", line 40, in <module>
  File "PyInstaller\loader\pyimod03_importers.py", line 540, in exec_module
  File "pynput\keyboard\__init__.py", line 31, in <module>
  File "pynput\_util\__init__.py", line 82, in backend
ImportError
[5644] Failed to execute script main

I went on to inspect the backend() function in "pynput_util__init\.py". The error seems to be caused by an "hidden" import on line 70:

importlib.import_module('._' + module, package)

and according to PyInstaller's docs here:

Hidden imports can occur when the code is using __import__(), importlib.import_module() or perhaps exec() or eval(). Hidden imports can also occur when an extension module uses the Python/C API to do an import. When this occurs, Analysis can detect nothing. There will be no warnings, only an ImportError at run-time.

From what i understand from the code in backend(), it's trying to load some moudle(s) for platform-dependent back-end support.

AnonymouX47 commented 3 years ago

I just found a fix, adding --collect-submodules pynput to the build command ensures the module being imported is also bundled. Thereby fixing the issue.

atridey commented 3 years ago

Strange, it successfully built just a couple of minutes ago (with collect submodules), but I tried doing it in WSL and it's getting an import error. I go back to windows to find that it's now also giving an importerror. I'll clone from scratch and try again.

AnonymouX47 commented 3 years ago

@daspartho What say you?

atridey commented 3 years ago

Alright, it magically fixed itself. Anyways, that's good news. We can now have prebuilt releases.

AnonymouX47 commented 3 years ago

but I tried doing it in WSL

WSL is a linux subsystem, not windows.

I'll try it on linux and see how it goes... though, i think running the script directly is still better since most recent linux systems come with Python 3.

atridey commented 3 years ago

I do agree with you on that. I also believe anyone willing to use Linux is probably tech savvy enough to install pip and dependencies. Still, prebuilt releases are always nice.

atridey commented 3 years ago

I did not mean to close

atridey commented 3 years ago

but I tried doing it in WSL

WSL is a linux subsystem, not windows.

I'll try it on linux and see how it goes... though, i think running the script directly is still better since most recent linux systems come with Python 3.

I'm well aware of that, I was testing if it worked on Linux but didn't feel like rebooting to get into actual Ubuntu.

AnonymouX47 commented 3 years ago

I do agree with you on that. I also believe anyone willing to use Linux is probably tech savvy enough to install pip and dependencies. Still, prebuilt releases are always nice.

True, and it won't cost anything much to add for linux also.

AnonymouX47 commented 3 years ago

I'm well aware of that, I was testing if it worked on Linux but didn't feel like rebooting to get into actual Ubuntu.

Oh, I see.

AnonymouX47 commented 3 years ago

I just tested it on linux also, works totally fine. I used this line on both Linux and Windows:

pyinstaller --onefile --hidden-import spotipy --collect-submodules pynput main.py

My only issue is with the sizes of the executables... i think downloading about 10mb for every update of the script would be worse than just downloading python and the dependencies once and updating the script.

AnonymouX47 commented 3 years ago

The following issues will be introduced by adding standalone executables:

  1. Inconsistency in path for credentials store, this applies when the program is executed from a CLI.
  2. How will updates be handled?

The way i see it, maybe this will only be done for Windows and MacOS. I said so because most linux users will generally start the program from a shell and not a file manager.

Elaborating on point 1, it's due to the fact that CWD will probably not be the same as the executable's location... and currently the script stores and loads credentials to/from the CWD.

AnonymouX47 commented 3 years ago
  1. Inconsistency in path for credentials store, this applies when the program is executed from a CLI.

This can be fixed for the file directly written/read by the script but i wonder how it'll be done for the username cache used by the Spotify API.

import-brain commented 3 years ago

@airD173 @AnonymouX47 It seems like PyInstaller allows use of the "--collect-all" argument for dependencies when calling it from the command line (this argument collects all submodules, binaries, and other stuff needed for successful use of the package). I just used py -m PyInstaller main.py -F --collect-all spotipy --collect-all pynput --collect-all py2app and it worked (See pull request #69).

I tried running it on a computer that doesn't even have Python installed, and it worked just fine.

AnonymouX47 commented 3 years ago

I think --collect-all option is unnecessary, just increases the executable size... I built it using the line in the README (which I added after testing) and it worked fine on Windows and Linux (and supposedly Mac OS, though I've not yet tested it).

Also, what's py2app doing there?