Search code examples
javascriptpythoneel

Eel function returns null


I was developing python program with Eel module. But there is problem. It's that return null from eel.getImgSrc(path) function to get image's byte data. Look at this code.

-----web/main.js------

async function run(path) {
    let n = await eel.getImgSrc(path)() //path is correct. but n is null.
    console.log(n);
}

-----app.py------

@eel.expose
def getImgSrc(path):
    f =  open(path, 'rb')
    return f.read()

Solution

  • In Eel, the Python and JavaScript layers communicate by passing JSON back-and-forth. Internally, the Python side is passing your Python return value through a function that's defined like this: jsn.dumps(obj, default=lambda o: None) which results in the string null in your case. You can confirm this behavior by updating your code for debugging purposes only to something like this:

    @eel.expose
    def getImgSrc(path):
        f =  open(path, 'rb')
    
        data = f.read()
        print(json.dumps(data, default=lambda o: None))
    
        return data
    
    

    You'll see it prints out null. That's why you're seeing null on the JavaScript side.

    I'm not a developer on the Eel project, so I can't explain the rationale of why this happens (I just see it in the source code). But now that you know it's happening, you can solve the problem by finding a way to encode your data so that it can be passed via JSON. (And you can use the sample code I posted above to check that it gets encoded properly.)

    A search on the web for how to encode binary data into JSON with Python and decode with JavaScript will yield many results... so pick one that suits your particular needs. One way that's common (and is discussed in an issue on the Eel project website), is to base64 encode the data on the Python side and then decode it on the JavaScript side. It's not ideal, but is a workable solution that I've used in the past. Your code would be something like this...

    -----web/main.js------

    async function run(path) {
        let n = await eel.getImgSrc(path)() // should no longer be null    
        console.log(atob(n));
    }
    

    -----app.py------

    @eel.expose
    def getImgSrc(path):
        f =  open(path, 'rb')
    
        data = f.read()
        data = base64.b64encode(data).decode("utf-8")
    
        return data
    

    Additionally, HTML image tags can accept base64 encoded data, so you could do something like:

    async function run(path) {
        let n = await eel.getImgSrc(path)() // should no longer be null    
        let imageEl = document.getElementById('image');
        imageEl.src = "data:image/jpeg;base64," + n;
        // any other processing...
    
    }
    
    

    You will probably need to tweak these examples to fit your exact needs.