python-eel / Eel

A little Python library for making simple Electron-like HTML/JS GUI apps
MIT License
6.44k stars 587 forks source link

Fixes to getting Electron to work #373

Open kakaroto opened 4 years ago

kakaroto commented 4 years ago

This PR includes 3 fixes. The first one is for #371 which I ended up forking/fixing, the other two were done in an attempt to get my app to run in electron for those that do not have chrome available. I wanted to include electron in my app, and found all sorts of issues, which this finally fixes.

The first issue I found is that setting the mode to "electron" on windows will cause an exception because if which returns None, you try a os.path.join(None, "../node_modules/etc...") which will fail.

The second issue is that I realized that no matter what I did, it wouldn't work because the run command adds "." as an argument, and while removing it fixed it, I believe you had that in there on purpose because it specifies the current working directory for an electron bundle, and I didn't want to change that as it would break for those using a different system than what I'm doing.

Basically, I just downloaded the electron binaries from their releases, extracted it under a subdir, added it to the PATH, and I want to run it directly from there. There is no bat file, and no node_modules here, and launching electron with "." as its first argument will fail because my app's current dir is not an electron bundle. Using "custom" mode was the only solution, but that launches cmdline_args but without adding the url to it, and since I use port=0 I had no way of hardcoding the url in the cmdline_args option either (and doing a block=false, and then trying to get the port to launch manually, and losing that whole websocket auto close thing, etc.. felt way too complicated than just adding a callback for custom modes).

So that's the explanation around where these commits are coming from, hopefully this gets accepted. Thanks!

kakaroto commented 4 years ago

Shouldn't it be .\node_modules\... since .. is 1 directory up/not the programs working dir? I was just trying to get electron/eel working on Win so I installed your master via pip.

I'm not exactly sure, I think the use of the node_modules path is somehow linked to the specific use case of the author here. I think that maybe the which is supposed to find electron.exe in a bin directory or something like that.

The way I did it is that I didn't use npm at all, I just downloaded the electron executable from https://github.com/electron/electron/releases and extract it in an Electron folder, then I use this :

  eel.start('index.html', port=0, mode="custom", custom_callback=self.PopenElectron)

with the PopenElectron function defined this way :

    def PopenElectron(self, args, urls):
        if platform.system() == 'Darwin':
            path = "Electron.app"
            if not os.path.exists(path):
                path = os.path.join(os.path.dirname(os.path.dirname(sys.executable)), "Resources", "Electron.app")
            cmd = ["open", "-a", path, "--args"]
        else:
            cmd = ["electron/electron"]
        cmd += args + [';'.join(urls)]
        return subprocess.Popen(cmd)

Which allows me to execute it it from my app's electron directory on windows, or from Electron.app on Mac, or from the Resources/Electron.app folder in my cx_freeze frozen app for Mac.

bitnom commented 4 years ago

I'm not exactly sure, I think the use of the node_modules path is somehow linked to the specific use case of the author here. I think that maybe the which is supposed to find electron.exe in a bin directory or something like that.

Let's do this then (Works for me):

def find_path():
    if sys.platform in ['win32', 'win64']:
        # It doesn't work well passing the .bat file to Popen, so we get the actual .exe
        bat_path = wch.which('electron')
        if bat_path is not None:
            exe_path = os.path.join(bat_path, r'..\node_modules\electron\dist\electron.exe')
            if os.path.exists(exe_path):
                return exe_path
            else:
                return bat_path
        else:
            exe_path = r'.\node_modules\electron\dist\electron.exe'
            if os.path.exists(exe_path):
                return exe_path
        return None
    elif sys.platform in ['darwin', 'linux']:
        # This should work find...
        return wch.which('electron')
    else:
        return None
kakaroto commented 4 years ago

Yeah, that makes sense, that would work and is less confusing to me with regards to how which is supposed to find a .bat file in a directory that isn't within the node_modules dir.