Pass JavaScript Variable Value to Python with Eel - python

I have a python program using eel library to build a nice GUI.
In the GUI I have a variable within a JS function that I need to pass to Python to store in a variable.
Any ideas why this is?

You can read the below Github article. Maybe this will help.
https://github.com/samuelhwilliams/Eel
Return values
While we want to think of our code as comprising a single application, the Python interpreter and the browser window run in separate processes. This can make communicating back and forth between them a bit of a mess, especially if we always had to explicitly send values from one side to the other.
Eel supports two ways of retrieving return values from the other side of the app, which helps keep the code concise.
To prevent hanging forever on the Python side, a timeout has been put in place for trying to retrieve values from the JavaScript side, which defaults to 10000 milliseconds (10 seconds). This can be changed with the _js_result_timeout parameter to eel.init. There is no corresponding timeout on the JavaScript side.
Callbacks
When you call an exposed function, you can immediately pass a callback function afterward. This callback will automatically be called asynchronously with the return value when the function has finished executing on the other side.
For example, if we have the following function defined and exposed in Javascript:
eel.expose(js_random);
function js_random() {
return Math.random();
}
Then in Python, we can retrieve random values from the Javascript side like so:
def print_num(n):
print('Got this from Javascript:', n)
# Call Javascript function, and pass explicit callback function
eel.js_random()(print_num)
# Do the same with an inline lambda as callback
eel.js_random()(lambda n: print('Got this from Javascript:', n))
(It works exactly the same the other way around).
Synchronous returns
In most situations, the calls to the other side are to quickly retrieve some piece of data, such as the state of a widget or contents of an input field. In these cases it is more convenient to just synchronously wait a few milliseconds then continue with your code, rather than breaking the whole thing up into callbacks.
To synchronously retrieve the return value, simply pass nothing to the second set of brackets. So in Python we would write:
n = eel.js_random()() # This immediately returns the value
print('Got this from Javascript:', n)
You can only perform synchronous returns after the browser window has started (after calling eel.start()), otherwise obviously the call with hang.
In Javascript, the language doesn't allow us to block while we wait for a callback, except by using await from inside an async function. So the equivalent code from the Javascript side would be:
async function run() {
// Inside a function marked 'async' we can use the 'await' keyword.
let n = await eel.py_random()(); // Must prefix call with 'await', otherwise it's the same syntax
console.log("Got this from Python: " + n);
}
run();

Related

Is there a way to delay a QueueMessage in Azure Functions?

I need to submit a message to Queue Storage, but not have it immediately trigger a function that is bound to that queue. In this basic example, I want to submit a message to a queue so that it triggers a function 1 minute later:
def main(msg: func.QueueMessage, outputQueueItem: func.Out[func.QueueMessage]) -> None:
data = msg.get_json()
# Do some fancy stuff
message = func.QueueMessage(body=json.dumps({"spam": 1, "eggs": "ham"}))
# This causes an AttributeError since you cant set time_next_visible
message.time_next_visible = datetime.utcnow() + timedelta(minutes=1)
outputQueueItem.set(message)
# More fancy stuff down here
I could throw in a time.sleep(60) before submitting the message, but that seems like bad practice, plus it would delay any other code below the line submitting the message and increase the billing cost of running the function. This is especially bad if there is a large delay necessary (e.g. an hour).
Is there any good way to delay the message from triggering the next function immediately?
Python can not use durable functions, so you have two ways to realize your ideas.
First is as you says, use sleep to make it wait.
Second is from the Python Azure SDK, use the put_message method to make the message stay in the queue(set the Visibility), take a look of how to use put_message.

Python code runs through entire switcher statement

I'm coding a bot using the discord.py api, was trying to simulate switch/cases for different commands to the bot
I read online that I can use switcher = { *some value* : *function* } to simulate switch/cases, but on specific values, its runs every function instead of the appropriate one
async def command_switcher(argument, message, parameters):
switcher= {
">autovc": await autovc_command_switcher(parameters[1], message,
parameters) if (len(parameters) > 1) else await
autovc_invalid(message),
">help": await default_help(message),
">vcgroup": await autovc_invalid(message)
}
return switcher.get(argument, "Invalid")
I call the command_switcher and pass in an argument, if the argument is ">help", then it properly only runs the default_help() function, but if I pass in ">autovc" it runs all 3 functions
Edit: also, if I switch the order of the entries, it still has the same result: ">help" still only runs itself, and ">autovc" still runs all 3
Edit 2: Solved thanks for the comments, while trying to create a proper MCVE as advised, and seeing the comment that dict values are the function objects, I figured out I was incorrectly calling the functions as opposed to referencing the function object itself. I was also having some issues with async/await, but the comment linking me to https://xinhuang.github.io/posts/2017-07-31-common-mistakes-using-python3-asyncio.html cleared that up for me as well

How to call the callback function within selenium execute_async_script from python

i am scraping one website, there is audio playing from the webpage, i want to know when will the audio finish playing, so i add event listener to the audio webElement to monitor 'onEnded' event to fire, and i want to get noticed from the callback() function within driver.execute_async_script.
but i always get error
TypeError: <function MissionContentItemHelper.audio_play_end at 0x10f3b7b70> is not JSON serializable.
my questions are:
1.does arguments[arguments.length - 1] refer to self.audio_play_end ?
2.why the error output is about 'MissionContentItemHelper.audio_play_end is not JSON serializable'? i can't see any clue between MissionContentItemHelper.audio_play_end and JSON.
3.is the way calling audio_play_end correct?
class MissionContentItemHelper:
def sleep(self):
audio = self.browser.find_element_by_css_selector('#audio')
self.browser.execute_async_script("""
var audio = arguments[0];
callback = arguments[arguments.length - 1];
audio.addEventListener("ended", function(_event) {
callback();
}
""", audio, self.audio_play_end)
#staticmethod
def audio_play_end():
print('the audio finished playing...')
execute_async_script's name confuses many people. It doesn't executes the script asynchronously from your test code, it only allows you to execute a script which runs asynchronously from the browser's main thread, like AJAX calls and JavaScript setTimeout.
These JavaScript functions and alike themselves return almost immediately, but they take a (JavaScript) function argument that is executed when the asynchronous operation completes. What execute_async_script does is exactly like execute_script, but instead of returning when the function itself returns (which is almost immediately) it provides its own callback JavaScript function (which it passes as the last argument, that's why the arguments[arguments.length - 1] is needed), that you can use in the JavaScript code you're passing into execute_async_script, to pass it on to the asynchronous function as the callback. execute_async_script returns only when this callback is called, instead of returning immediately.
For example, in the following code, the call to execute_async_script acts like a delay of 2 seconds:
browser.execute_async_script("setTimeout(arguments[0], 2000)")
Note that because I didn't pass any additional arguments to the script, then arguments[0] is actually the last argument.
In your case, you don't have to pass self.audio_play_end, but you have to call audio.play() inside your JavaScript snippet to start the audio. execute_async_script should return only when the audio is finished playing.
Usage works as following:
# driver allready i initialised
js = """
var done = arguments[0];
// my_async_acript here ..
.then(value=>done(value)
"""
value = driver.execute_async_script(js)
Call javascript function done(value) with the value you want to return.
Note: If you're getting a timeout-exception, check the developer-console for errors
This actually is a dublicate I think reference
It's important to know that the last argument passed is the promise resolver. That means:
self.browser.execute_async_script("""
let [element, resolve] = arguments
element.addEventListener("ended", resolve)
""", audio)

How to keep a While True loop running with raw_input() if inputs are seldom?

I'm currently working on a project where I need to send data via Serial persistently but need to occasionally change that data based in new inputs. My issue is that my current loop only functions exactly when a new input is offered by raw_input(). Nothing runs again until another raw_input() is received.
My current (very slimmed down) loop looks like this:
while True:
foo = raw_input()
print(foo)
I would like for the latest values to be printed (or passed to another function) constantly regardless of how often changes occur.
Any help is appreciated.
The select (or in Python 3.4+, selectors) module can allow you to solve this without threading, while still performing periodic updates.
Basically, you just write the normal loop but use select to determine if new input is available, and if so, grab it:
import select
while True:
# Polls for availability of data on stdin without blocking
if select.select((sys.stdin,), (), (), 0)[0]:
foo = raw_input()
print(foo)
As written, this would print far more than you probably want; you could either time.sleep after each print, or change the timeout argument to select.select to something other than 0; if you make it 1 for instance, then you'll update immediately when new data is available, otherwise, you'll wait a second before giving up and printing the old data again.
How will you type in your data at the same time while data is being printed?
However, you can use multithreading if you make sure your source of data doesn't interfere with your output of data.
import thread
def give_output():
while True:
pass # output stuff here
def get_input():
while True:
pass # get input here
thread.start_new_thread(give_output, ())
thread.start_new_thread(get_input, ())
Your source of data could be another program. You could connect them using a file or a socket.

Return continuous result from a single function call

I have got stuck with a problem.
It goes like this,
A function returns a single result normally. What I want is it to return continuous streams of result for a certain time frame(optional).
Is it feasible for a function to repeatedly return results for a single function call?
While browsing through the net I did come across gevent and threading. Will it work if so any heads up how to solve it?
I just need to call the function carry out the work and return results immediately after every task is completed.
Why you need this is not specified in the question, so it is hard to know what you need, but I will give you a general idea, and code too.
You could return in that way: return var1, var2, var3 (but that's not what you need I think)
You have multiple options: either blocking or non-blocking. Blocking means your code will no longer execute while you are calling the function. Non-blocking means that it will run in parallel. You should also know that you will definitely need to modify the code calling that function.
That's if you want it in a thread (non-blocking):
def your_function(callback):
# This is a function defined inside of it, just for convenience, it can be any function.
def what_it_is_doing(callback):
import time
total = 0
while True:
time.sleep(1)
total += 1
# Here it is a callback function, but if you are using a
# GUI application (not only) for example (wx, Qt, GTK, ...) they usually have
# events/signals, you should be using this system.
callback(time_spent=total)
import thread
thread.start_new_thread(what_it_is_doing, tuple(callback))
# The way you would use it:
def what_I_want_to_do_with_each_bit_of_result(time_spent):
print "Time is:", time_spent
your_function(what_I_want_to_do_with_each_bit_of_result)
# Continue your code normally
The other option (blocking) involves a special kind of functions generators which are technically treated as iterators. So you define it as a function and acts as an iterator. That's an example, using the same dummy function than the other one:
def my_generator():
import time
total = 0
while True:
time.sleep(1)
total += 1
yield total
# And here's how you use it:
# You need it to be in a loop !!
for time_spent in my_generator():
print "Time spent is:", time_spent
# Or, you could use it that way, and call .next() manually:
my_gen = my_generator()
# When you need something from it:
time_spent = my_gen.next()
Note that in the second example, the code would make no sense because it is not really called at 1 second intervals, because there's the other code running each time it yields something or .next is called, and that may take time. But I hope you got the point.
Again, it depends on what you are doing, if the app you are using has an "event" framework or similar you would need to use that, if you need it blocking/non-blocking, if time is important, how your calling code should manipulate the result...
Your gevent and threading are on the right track, because a function does what it is programmed to do, either accepting 1 var at a time or taking a set and returning either a set or a var. The function has to be called to return either result, and the continuous stream of processing is probably taking place already or else you are asking about a loop over a kernel pointer or something similar, which you are not, so ...
So, your calling code which encapsulates your function is important, the function, any function, eg, even a true/false boolean function only executes until it is done with its vars, so there muse be a calling function which listens indefinitely in your case. If it doesn't exist you should write one ;)
Calling code which encapsulates is certainly very important.
Folks aren't going to have enough info to help much, except in the super generic sense that we can tell you that you are or should be within in some framework's event loop, or other code's loop of some form already- and that is what you want to be listening to/ preparing data for.
I like "functional programming's," "map function," for this sort of thing. I think. I can't comment at my rep level or I would restrict my speculation to that. :)
To get a better answer from another person post some example code and reveal your API if possible.

Categories

Resources