I have a callback in Flask+dash
server = Flask(__name__, static_folder='static')
app = dash.Dash(external_stylesheets=external_stylesheets, server=server)
thus:
#server.route("/Data/<symbol>")
def Data(symbol):
ib.qualifyContracts(symbol)
This gives a warning (in actuality it is an error):
RuntimeWarning:
coroutine 'IB.qualifyContractsAsync' was never awaited
However, if I put async in front of def soo I can await the function call (but not even inserting the await yet):
#server.route("/Data/<symbol>")
async def Data(symbol):
ib.qualifyContracts(symbol)
I get an exception
TypeError
TypeError: The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a coroutine.
How does one deal with dash callbacks that need to call other functions that need to be awaitable?
Related
I am running a python program to listen to azure iot hub. The function is returning me a coroutine object instead of a json. I saw that if we use async function and call it as a normal function this occurs, but i created a loop to get event and then used run_until_complete function. What am i missing here?
async def main():
try:
client = IoTHubModuleClient.create_from_connection_string(connection_string)
print(client)
client.connect()
while True:
message = client.receive_message_on_input("input1") # blocking call
print("Message received on input1")
print(type(message))
print(message)
except KeyboardInterrupt:
print ( "IoTHubClient sample stopped" )
except:
print ( "Unexpected error from IoTHub" )
return
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
OUTPUT-
Message received on input1
<class 'coroutine'>
<coroutine object receive_message_on_input at 0x7f1439fe3a98>
Long story short: you just have to write await client.receive_message_on_input("input1"). Your main is a coroutine, but receive_message_on_input is a coroutine as well. You must wait for it to complete.
I could tell you the story, but it's too long really. :)
await room.save()
showing the below error
AttributeError: 'NoneType' object has no attribute 'execute_insert'
startUp code
async def init():
# Here we create a SQLite DB using file "db.sqlite3"
# also specify the app name of "models"
# which contain models from "app.models"
await Tortoise.init(
db_url='sqlite://db1',
modules={'app1': ['app1.models']}
)
# Generate the schema
#await Tortoise.generate_schemas()
#app.on_event("startup")
async def startup_event():
nest_asyncio.apply()
run_async(init())
created a db structure that's why commented await Tortoise.generate_schemas().
Find my post method code below
#app.post("/room/{room_id}")
async def post(request: Request, room_id):
room = models.Room(id=room_id)
await room.save()
return {"message":"created successfully"}
In the #app.on_event("startup") which is an async function, you are calling run_async(init()) which according to the documentation cleans up after itself, and is meant for small scripts only.
Meaning you are creating and then destroying the DB connection. Hence the connection being a None.
Instead, just await it, and handle shutdown event like so:
#app.on_event("startup")
async def startup_event():
nest_asyncio.apply()
await init()
#app.on_event("shutdown")
async def close_orm():
await Tortoise.close_connections()
Edit: Apparently there is also issues with nest_asyncio and just leaving it out makes things work better.
I'm trying to write a HTTP server that sends a HTTP request and returns the content to client.
Here is the code:
import asynchttpserver, asyncdispatch
import httpClient
let client = newHttpClient()
var server = newAsyncHttpServer()
proc cb(req: Request) {.async.} =
let content = client.getContent("http://google.com")
await req.respond(Http200, content)
waitFor server.serve(Port(8080), cb)
However, I obtain the following compile error message (nim v1.0.0):
Error: type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.locks: <unknown>.}>
but expected one of:
proc serve(server: AsyncHttpServer; port: Port;
callback: proc (request: Request): Future[void] {.closure, gcsafe.};
address = ""): owned(Future[void])
first type mismatch at position: 3
required type for callback: proc (request: Request): Future[system.void]{.closure, gcsafe.}
but expression 'cb' is of type: proc (req: Request): Future[system.void]{.locks: <unknown>.}
This expression is not GC-safe. Annotate the proc with {.gcsafe.} to get extended error information.
expression: serve(server, Port(8080), cb)
The serve function expects another expression but do not know how to fix it.
Surprisingly, the code compiles perfectly fine when I remove the HTTP request from the server callback "cb". Does this mean that the serve function expects different callback expressions depending on the callback body ?
OK the problem is that the HttpClient is a global variable and is used in the callback function "cb". As a result the callback function is not GC safe.
So it is enough to instantiate the HttpClient within the callback function:
import asynchttpserver, asyncdispatch
import httpClient
var server = newAsyncHttpServer()
proc cb(req: Request) {.async.} =
let client = newHttpClient()
let content = client.getContent("https://google.com")
await req.respond(Http200, content)
waitFor server.serve(Port(8080), cb)
I watched an asyncio Pycon video on youtube where the presenter in one of her examples said she was using asyncio.create_task to run the coroutine instead of await, as await would block the execution of the coroutine until whatever it is awaiting is complete. I thought asyncio.create_task returns a Task which needs to be await. Nevertheless, I ran test using the following code and I am somewhat surprised by its result.
async def say_hello():
print("Hello")
await asyncio.sleep(0.5)
print("World")
async def run_coro(coro):
asyncio.create_task(coro)
asyncio.run(run_coro(say_hello()))
The code above prints only Hello. I figured that asyncio.create_task in run_coro stops execution as soon as it reaches the await line in say_hello. If I rewrite say_hello as follows and the run it using run_coro I see all the lines before `await asyncio.sleep(0.5) printed on the terminal
async def say_hello():
print("Hello")
print("Hello")
print("Hello")
print("Hello")
await asyncio.sleep(0.5)
print("World")
If I rewrite run_coro as follows then all the lines get printed as expected:
async def run_coro(coro):
asyncio.create_task(coro)
await asyncio.sleep(1)
Can anyone tell why?
Because
asyncio.run actually calls loop.run_until_complete, which means the main program will exit as soon as run_coro returns. So the scheduler does not have chance to run say_hello
asyncio.create_task(coro) runs coro in the background
if you change your code to
async def run_coro(coro):
asyncio.create_task(coro)
await asyncio.sleep(0.49)
coro actually only runs for 0.49 seconds, so you still can not see print("World")
You need to suspend the current task by blocking coroutine or using await so that the next task can be done, which is why having await asyncio.sleep(1) work as expected. See more: here
I am getting my feet wet with Meteor's HTTP methods.
As a test, I am hitting Twitter's api with a method on the server, as follows:
"twitter_user": () ->
Meteor.http.get("https://api.twitter.com/1/users/show.json", {screen_name:"ppedrazzi"})
On the client, I call the method as follows:
twitterUser = Meteor.call("twitter_user")
When trying to access the twitterUser object, it shows as undefined. I was expecting to be able to use twitterUser.data.id or twitterUser.data.name to grab the fields from the resulting JSON, but no luck (since the object does not exist).
Incidentally, if I drop the URL into the browser, I get a JSON object on the page, see example here:
https://api.twitter.com/1/users/show.json?screen_name=ppedrazzi
You should use an async call to your method:
Meteor.call "twitter_user", (error, result) ->
twitterUser = result
Citation from the documentation:
On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method. That is because the client doesn't have fibers, so there is not actually any way it can block on the remote execution of a method.
Note that in this particular case, you can run Meteor.http.get directly on the client:
Meteor.http.get(
"https://api.twitter.com/1/users/show.json",
screen_name:"ppedrazzi",
(error, result) -> twitterUser = result
)