In Python Lan Ref. 3.4.4, it is said that __aenter__() and __aexit__() must return awaitables. However, in the example async context manager, these two methods return None:
class AsyncContextManager:
async def __aenter__(self):
await log('entering context')
async def __aexit__(self, exc_type, exc, tb):
await log('exiting context')
Is this code correct?
__aenter__ and __aexit__ must return awaitables, but look what happens when you call the ones in the example:
>>> class AsyncContextManager:
... async def __aenter__(self):
... await log('entering context')
... async def __aexit__(self, exc_type, exc, tb):
... await log('exiting context')
...
>>> AsyncContextManager().__aenter__()
<coroutine object AsyncContextManager.__aenter__ at 0x7f5b092d5ac0>
It didn't return None! We got a coroutine object, which is awaitable.
These methods are async functions, which automatically return (awaitable) asynchronous coroutines. return statements in the body of an async function determine what gets returned when you await the coroutine, not what gets returned when you call the function.
This is similar to how generator functions return generator iterators, even though they usually have no return statement, and how if you write __iter__ as a generator function, you should not try to return an iterator inside the generator function.
So what happens if you do put a return in __aenter__ or __aexit__ defined as async functions? Well, you can, and if you do, the return statement doesn't have to return an awaitable. Here's what Python will do.
If you return something from an __aenter__ defined as an async function, that determines what gets bound to an as target, if the async with uses as.
If you return something from an __aexit__ defined as an async function, that determines whether to suppress exceptions that got raised inside the block. A "truthy" value tells the async with to suppress exceptions, while a "falsy" value tells the async with to let exceptions propagate. The default None is falsy, so by default, exceptions are not suppressed.
Here's an example:
import asyncio
class Example:
async def __aenter__(self):
return 3
async def __aexit__(self, exc_type, exc, tb):
return True
async def example():
async with Example() as three:
print(three == 3)
raise Exception
print("Exception got suppressed")
asyncio.run(example())
Output:
True
Exception got suppressed
Your __aenter__ method must return a context.
class MyAsyncContextManager:
async def __aenter__(self):
await log('entering context')
# maybe some setup (e.g. await self.setup())
return self
async def __aexit__(self, exc_type, exc, tb):
# maybe closing context (e.g. await self.close())
await log('exiting context')
async def do_something(self):
await log('doing something')
usage:
async with MyAsyncContextManager() as context:
await context.do_something()
Related
Python version: 3.6
I am not super expert in Python, I was trying to use Tornado to implement a simple REST server and use non blocking coroutine to call a blocking function. When I return Json from the blocking function it fails with TypeError: 'dict' object is not callable
Here's the code
#gen.coroutine
def post(self):
jsonResponse = yield self.process_request(imageBytes)
self.write(json.dumps(jsonResponse))
#gen.coroutine
def process_request(self, imageBytes):
response = yield (executor.submit(self.test_func(), None))
return response
def test_func(self):
print('test func')
time.sleep(1)
jsonDataSet = {"text": "hello 123"}
return jsonDataSet
I am not sure what I am doing wrong, followed the sample code from Tornado reference. Any pointers will be helpful?
Latest:
I moved to async & await now I am getting "Object of type 'coroutine' is not JSON serializable"
async def test_func():
print('test func')
time.sleep(1)
jsonDataSet = {"text": "hello 123"}
return jsonDataSet
#return "test"
response = await `tornado.ioloop.IOLoop.current().run_in_executor(None, test_func)`
TypeError: 'dict' object is not callable
executor.submit() requires a callable, but you're already calling the test_func function. When you call test_func(), you're essentially passing its return value (which is a dict) to the submit() function.
You need pass this function without calling:
executor.submit(self.test_func, None)
Latest: I moved to async & await now I am getting "Object of type 'coroutine' is not JSON serializable"
run_in_executor is for running a normal function in a separate thread. It's not meant for running coroutines.
What's happening here is run_in_executor is calling test_func() coroutine, which automatically returns an awaitable object (because it's a coroutine).
If you want to execute test_func using run_in_executor, just make it a normal function (don't use async def).
I'm trying to figure out how to refresh the client-side component after button click.
Repo Link with example: https://github.com/ovie91/RefreshComponent
Site /test or from nav menu test
So I have OnInitializedAsync method that is retrieving data from API
protected override async Task OnInitializedAsync()
{
result = await (some API Call);
}
Then I have a method connected to the button
private async void ButtonClick()
{
await (some API Call);
result = null;
this.StateHasChanged(); <--- Doesnt work :<
}
I have tried to use this.StateHasChanged(); but there is no reaction.
As a workaround, I can force you to navigate again to the same website but this refresh "Whole" website but not a component.
Any ideas on how to deal with it?
whole code (stripped to minimum):
#page "/test"
#inject HttpClient Http
#if (result == null)
{
<p>Loading...<p>
}
else
{
#result
<button #onclick="(() => ButtonClick())">Click</button>
}
#code {
private APIObject result;
protected override async Task OnInitializedAsync()
{
result = await (some API Call);
}
private async void ButtonClick()
{
await (some API Call);
result = null;
this.StateHasChanged(); <--- Doesnt work :<
}
}
Update
I want to refresh component so OnInitializedAsync would be triggered again and that would mean I don't have to run the same code again after button click. Hope you understand what I mean.
To get the desired output you just have to shuffle the lines a little, from:
private async void ButtonClick()
{
await (some API Call); // UI checks if an update is needed (No)
result = null; // now an update is needed
this.StateHasChanged(); <--- Doesnt work :< // actually: not needed
}
to:
private async Task ButtonClick()
{
result = null; // change the state
//this.StateHasChanged(); // not needed, a request is pending
await (some API Call); // should show '<h3>Loading</h3>' now
}
Note that the UI is updated when an await releases the Thread.
however, from your answer we get
var APICall = await Http.GetAsync("SomeAPI");
Thread.Sleep(2000);
This should work when Http.GetAsync("SomeAPI"); really is an async call and not just some stand-in pseudo code. Because Thread.Sleep(2000); will really freeze things.
If you want to make sure:
private async Task GetData()
{
await Task.Delay(1); // release the thread for rendering
var APICall = await Http.GetAsync("SomeAPI");
Random rnd = new Random();
Thread.Sleep(2000); // Task.Delay() is much preferred
result = "Random Number: " + rnd.Next();
}
Thread.Sleep() is appropriate to simulate some CPU (not I/O) intensive code. So I'm not saying it's wrong but be aware of the difference.
And it is much better to make eventhandlers async Task instead of async void but that is not the direct problem here.
From here:
Blazor uses a synchronization context (SynchronizationContext) to enforce a single logical thread of execution. A component's lifecycle methods and any event callbacks that are raised by Blazor are executed on the synchronization context.
Blazor Server's synchronization context attempts to emulate a single-threaded environment so that it closely matches the WebAssembly model in the browser, which is single threaded. At any given point in time, work is performed on exactly one thread, giving the impression of a single logical thread. No two operations execute concurrently.
So as enet asnwered, you should use async Task signature instead of async void.
I have moved API call to another Method and inside of OnInitializedAsync I called it.
Then when I reset the result variable to see Loading state I'm able to "refresh" component to achieve that you need to add. this.StateHasChanged()
Now I have a responsive component to updates that are happening :)
#page "/test"
#using System.Threading;
#inject HttpClient Http
#if (result == null)
{
<h3>Loading</h3>
}
else
{
#result
<button #onclick="(() => ButtonClick())">Click</button>
}
#code {
private string result;
protected override async Task OnInitializedAsync()
{
await GetData();
}
private async Task GetData()
{
var APICall = await Http.GetAsync("SomeAPI");
Random rnd = new Random();
Thread.Sleep(2000);
result = "Random Number: " + rnd.Next();
}
private async Task ButtonClick()
{
await Http.GetAsync("SomeAPIcall");
result = null; // required to see loading state.
this.StateHasChanged(); // when added model is refreshed and Loading state is visible.
await GetData();
}
}
I have a fetch instruction in one function that grabs an API key from a server and it's used by a few other objects to deliver that API key to whatever service needs it.
export default async function getAPIKey(key) {
return await (await fetch('http://localhost:8000/' + key)).json();
}
And in my weather object:
export default {
URI: 'https://api.openweathermap.org',
getLocalWeather: async function(city=null, countryCode=null) {
try {
// fetch the API key from environment
const API_KEY = await getAPIKey('wx');
//... rest of code
The code as it is works, but I don't understand why I need 3 await statements. Wouldn't I only need two? I need one for the fetch() in getAPIKey(). Then .json() returns a promise because it has to wait for the response body, so I'd need an await where I call the function in getLocalWeather(). But if I don't have two awaits in getAPIKey() it just returns [object Response]?
Essentially I'm wondering why the following is wrong:
export default async function getAPIKey(key) {
return (await fetch('http://localhost:8000/' + key)).json();
}
And in my weather object:
export default {
URI: 'https://api.openweathermap.org',
getLocalWeather: async function(city=null, countryCode=null) {
try {
// fetch the API key from environment
const API_KEY = await getAPIKey('wx');
//... rest of code
Am I miss-counting? Because I only see two Promises. I know async/await functions are promises under the hood, so getAPIKey() is a promise, but wouldn't that promise be the .json() Promise? And if so why isn't the await where I call the function sufficient?
I'm not sure what what I'm failing to understand.
You don't need any of those await statements inside of getAPIKey() and your function doesn't even need to be async. You can just do this:
export default function getAPIKey(key) {
return fetch('http://localhost:8000/' + key).json();
}
You just want to return the promise from fetch().json().
The code as it is works, but I don't understand why I need 3 await statements. Wouldn't I only need two?
Actually, you only need one when you do await getAPIKey(). The others inside of getAPIKey() are not needed at all.
When you do something like:
export default async function getAPIKey(key) {
return await fetch('http://localhost:8000/' + key).json();
}
You're just adding a superfluous await that has no benefit. The function returns a promise (all async functions return a promise) and that promise is resolved when the await is done which is exactly the same as just doing return fetch('http://localhost:8000/' + key).json(); in the first place. Adding the second await also adds no value.
promises are executed only if you call .then on them
or this is how I learned it.
Async functions are what I understand functions "turned" promises. Do I need to call .then on them each time I want to invoke an async function?
async function loadStory(){}
....
loadStory()
or
loadStory().then
Async functions are executed as per regular functions by invoking them as usual.
In order to make your code appear synchronous and utilise the benefits of async / await you'll need to prefix the call with await.
For example:
async function example () {
return new Promise(resolve => {
resolve('hello');
});
}
const myReturnedValue = await example();
Because of the await keyword, myReturnedValue will be the result of the resolved promise returned by the example function.
I'm new to async / await, and have been trying to implement it in my 4.6 web api 2 project.
public class MyController : ApiController
{
public async Task<Thing> Search(String searchTerms)
{
myThing = new Thing();
myThing.FirstProperty = await doFirstPropertyAsync(searchTerms);
myThing.SecondProperty = await doSecondPropertyAsync(searchTerms);
return myThing;
}
}
Basically I'm returning a class (Thing) that has two properties that take a few seconds each to populate. I'm actually loading maybe ~10 properties, but it's the same logic for all of them.
public async Task<MyCoolSubObject> doFirstPropertyAsync(string searchTerms)
{
SomeController sController = new SomeController();
Debug.WriteLine("first - starting.");
var x = await Task.Run(()=>sController.Lookup(searchTerms));
Debug.WriteLine("first - finishing.");
return x;
}
public async Task<MyCoolSubObject> doSecondPropertyAsync(string searchTerms)
{
SomeOtherController sController = new SomeOtherController();
Debug.WriteLine("second - starting.");
var x = await Task.Run(()=>sController.Lookup(searchTerms));
Debug.WriteLine("second - finishing.");
return x;
}
What's got my scratching my head:
When I look at the debug outputs, the first property assignment method call starts and finishes before the second completes. Again, I actually have like ten of these and no matter what order I put the property assignments in they complete in a serial fashion (ie: nothing starts until another one finishes).
These property assignments under the hood are basically doing database calls that take a while, hence I wanted them running in parallel if possible. The methods themselves ( SomeController.Lookup(string) ) contain no await/async/task stuff.
Again, I actually have like ten of these and no matter what order I
put the property assignments in they complete in a serial fashion (ie:
nothing starts until another one finishes).
This happens because in your code you use the await keyword as soon as you kickoff the task, by doing that you prevent the method to continue to execute the next statement before the task will be done.
If you want to run your tasks in parallel you should kickoff all of them and only then await all of them using Task.WhenAll:
public async Task<Thing> Search(String searchTerms)
{
myThing = new Thing();
var firstTask = doFirstPropertyAsync(searchTerms);
var secondTask = doSecondPropertyAsync(searchTerms);
await Task.WhenAll(firstTask, secondTask);
myThing.FirstProperty = await firstTask;
myThing.SecondProperty = await secondTask;
return myThing;
}
Note that when we await every task separately after we await Task.WhenAll the tasks have already been done, we do that in order to get the result from the task, although we can use the Result property (it will not block since we know the task has already been done) I prefer to use await for consistency reasons.