I am using Azure Functions and python to connect to a PostgreSQL database. I would like to use the psycopg3 library and an AsyncConnectionPool to do so.
psycopg requires you to change the default event loop policy (e.g. with asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
), which I do but I still get errors. I think this is because the asyncio policy gets set before I get the chance to call asyncio.set_event_loop_policy()
. How can I work around this? I could use non-async connections if I needed to, but I’d rather stick with async for the performance benefits.
Code to reproduce:
#function_app.py
import azure.functions as func
import psycopg_pool
import json
import asyncio
import os
if os.name == 'nt':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
con_str = "host=localhost dbname=test-db user=postgres password=admin"
apool = psycopg_pool.AsyncConnectionPool(
conninfo=con_str,
open = False
)
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)
async def connect():
await apool.open()
await apool.wait()
print("Connect OK")
@app.route(route="info", auth_level= func.AuthLevel.FUNCTION)
async def info_trigger(req: func.HttpRequest) -> func.HttpResponse:
try:
await connect()
status = {"test": "OK"}
except:
status = {"test": "Not ok"}
return func.HttpResponse(
json.dumps(status),
status_code=200,
mimetype='application/json'
)
if __name__ == "__main__":
asyncio.run(connect())
If I run function_app.py from command line (py function_app.py
) I get the “Connect OK” printout as expected.
If I launch the server locally with func host start
and send a request via postman, I get {test: "Not ok"}
as a response and the console that I launched the host from repeats the following printout:
error connecting in 'pool-1': Psycopg cannot use the 'ProactorEventLoop' to run in async mode. Please use a compatible event
loop, for instance by setting 'asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())'
Nick is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
You could try to set this in __init__.py
:
/ function_app_folder
├─ __init__.py
├─ function_app.py
__init__.py
:
import asyncio
import os
if os.name == 'nt':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
And remove this code from function_app.py
.
By placing it in __init__.py
you ensures, that policy setting before function_app.py
2