How to get currently running EventLoop in python36? - python-3.6

I know that in python37 we have a new api asyncio.get_running_loop(), which is easy to use, let us do not need to pass eventloop explicitly when we call a coroutine.
I'm wondering if there's any approach we can use to get the same effect in python36?
# which allows us coding conveniently with this api:
import asyncio
async def test():
print("hello world !")
async def main():
loop = asyncio.get_running_loop()
loop.create_task(test())
asyncio.run(main())

In Python 3.6 you can use asyncio.get_event_loop() for equivalent effect.
According to the documentation, it is equivalent to calling get_event_loop_policy().get_event_loop(), which is in turn documented to return "the currently running event loop" when called from a coroutine.
In other words, when invoked from a coroutine (or from a function invoked by a coroutine), there is no difference between get_event_loop and get_running_loop, both will return the running loop. It is only when no loop is running that get_event_loop() will keep returning the loop associated with the current thread, while get_running_loop() will raise an exception. As long as you are careful to call get_event_loop() while a loop is actually running, it will be equivalent to get_running_loop().
Note that get_event_loop returning the running loop when called from a coroutine is new to Python 3.6 and 3.5.3. Prior to those versions, get_event_loop would always return the event loop associated with the current thread, which could be a different loop from the one that is actually running. This made get_event_loop() fundamentally unreliable and is the reason why old asyncio code would pass the loop argument everywhere. More details here.

Related

Single threaded asynchronous event loop with `winit`

I'm trying to build an NES emulator using winit, which entails building a game loop which should run exactly 60 times per second.
At first, I used std::thread to create a separate thread where the game loop would run and wait 16 milliseconds before running again. This worked quite well, until I tried to compile the program again targeting WebAssembly. I then found out that both winit::window::Window and winit::event_loop::EventLoopProxy are not Send when targeting Wasm, and that std::thread::spawn panics in Wasm.
After some struggle, I decided to try to do the same thing using task::spawn_local from one of the main asynchronous runtimes. Ultimately, I went with async_std.
I'm not used to asynchronous programming, so I'm not even sure if what I'm trying to do could work.
My idea is to do something like this:
use winit::{window::WindowBuilder, event_loop::EventLoop};
use std::time::Duration;
fn main() {
let event_loop = EventLoop::new();
let _window = WindowBuilder::new()
.build(&event_loop);
async_std::task::spawn_local(async {
// game loop goes here
loop {
// [update game state]
// [update frame buffer]
// [send render event with EventLoopProxy]
async_std::task::sleep(Duration::from_millis(16)).await;
// ^ note: I'll be using a different sleep function with Wasm
}
});
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
match event {
// ...
_ => ()
}
});
}
The problem with this approach is that the game loop will never run. If I'm not mistaken, some asynchronous code in the main thread would need to be blocked (by calling .await) for the runtime to poll other Futures, such as the one spawned by the spawn_local function. I can't do this easily, since event_loop.run is not asynchronous.
Having time to await other events shouldn't be a problem, since the control flow is set to wait.
Testing this on native code, nothing inside the game loop ever runs. Testing this on Wasm code (with wasm_timer::Delay as the sleep function), the game loop does run, but at a very low framerate and with long intervals of halting.
Having explained my situation, I would like to ask: is it possible to do what I'm trying to do, and if it is, how would I approach it? I will also accept answers telling me how I could try to do this differently, such as by using web workers.
Thanks in advance!

Scalamock expect eventually

I'm using scalamock to write a test. The problem is that action is asynchronous.
I have the following pseudo code
val resultCollectorMock = mock[ResultCollector]
(resultCollectorMock.collectResult _).expect(someResult)
val serviceUnderTest = new ServiceUnderTest(resultColletorMock)
serviceUnderTest.runAsyncJob(someParams)
This fails because the result is computed asynchronously, at time when the test ends, it's still not ready, so collectResult wasn't called, yet.
What I want to have is expectEventually(value)(patienceConfig) that is able to wait for some time for the method to be called.
I tried to use a sutb and verify instead, I wrapped it in eventually from scalatest but to no avail. For whatever reason verify seems to break the test at first evaluation.
you should use AsyncMockFactory with an appropriate test suite and Futures as described in the docs at https://scalamock.org/user-guide/integration/

Why Future works after the main function was done?

In the example on dart.dev the Future prints the message after the main function was done.
Why might the Future work after the main function was done? At first glance, after the completion of the main function, the entire work of the program is expected to be completed (and the Future must be cancelled).
The example code:
Future<void> fetchUserOrder() {
// Imagine that this function is fetching user info from another service or database.
return Future.delayed(Duration(seconds: 2), () => print('Large Latte'));
}
void main() {
fetchUserOrder();
print('Fetching user order...');
}
The program prints
Fetching user order...
Large Latte
I've expected just the following
Fetching user order...
This has to do with the nature of futures and asynchronous programming. Behind the scenes, Dart manages something called the asynchronous queue. When you initiate a future (either manually like you did with Future.delayed or implicitly by calling a method marked async, that function's execution goes into the queue whenever its execution gets deferred. Every cycle when Dart's main thread is idle, it checks the futures in the queue to see if any of them are no longer blocked, and if so, it resumes their execution.
A Dart program will not terminate while futures are in the queue. It will wait for all of them to either complete or error out.

Asynchronous UDFs and xleventCalculationCanceled

As soon as I press "Enter" after I wrote an asynchronous function into a cell, the async function is correctly called, and Excel raises the event xleventCalculationEnded when the calculation is finished.
However, if I press another cell just after I clicked "Enter" , the event xleventCalculationCanceled is raised, and then the async function is called another time ! Is this behavior normal ? Should I return a result via the Excel12(xlAsyncReturn,...) for the first async call , for the second async call or for both ?
In other word, does the xleventCalculationCanceled event implies that I'm not forced to return a result to Excel ? (using the appropriate asyncHandle)
I'm using async functions to delegate intensive computation in another thread and to not block excel during computation. However if the async function is called automatically two times (as it is the case when the user click another cell without waiting for the first call to finish) then the intensive computation are computed two times for the same input (because the first call -cancelled by excel- still live in the delegate thread...) How do you deal with this problem ?
Two calls for the same function - with the same input - is it a bug ?
Many thanks
What you describe is the normal behaviour. Excel cancels and then restarts the async calculations when there is user interaction (and can do so multiple times).
The documentation suggest that:
xleventCalculationEnded will fire directly after xleventCalculationCanceled, and
You can release any resources allocated during the calculation when xleventCalculationEnded fires. I understand that to include any asyncHandle you might have, and thus that you need not return any result based on the handle.
If your long-running function allows cancellation while in flight, you can cancel the work you do. Otherwise, you might do some internal bookkeeping on what function calls are in flight, and prevent doing the work twice yourself that way.

Access python function from javascript in QWebView

I am writing a Python/PyQt4 application that generates and displays a page in a QWebView widget. The page includes javascript code that I would like to be able to call functions returning data from the python application.
So far I can call functions that do not return data (using the pyqtSlot decorator), and call functions that do take parameters by exposing them as properties (using the pyqtProperty decorator). What I haven't worked out how to do is to call a python function with parameters, that returns data.
The question 9615194 explains how to do this from C++, but I cannot see how to transfer this to PyQt4.
I suspect you're not using the result= keyword to specify the return value in your pyqtSlot decorator?
#pyqtSlot(str, result=str)
def echo(self, phrase):
return self.parent().echo(phrase)
I ran afoul of this myself recently. No errors are generated if you omit result=, the method just silently returns nothing. Pretty maddening 'til I figured it out. See my answer to this question for a worked example.

Resources