为什么使用 aioodbc 而不是 pyodbc 和 asyncio?

问题描述 投票:0回答:1

我是 python 编程新手,目前正在学习使用 asyncio 的异步编程。我使用 asyncio 从 sql server 数据库异步读取数据,效果很好。我的问题是,当我学习这样做时,我遇到了一个名为“aioodbc”的 python 库,它指出***“aioodbc 是 Python 3.5+ 模块,可以使用 asyncio 访问 ODBC_ 数据库。”


但是使用 asyncio 库和 pyodbc 可以相当轻松地做到这一点吗?那么为什么要使用 aioodbc 而不是 pyodbc 和 asyncio 呢?我在这里错过了什么吗?

我在下面附上了我用来测试这个的代码,任何对此的反馈将不胜感激

import asyncio
import pyodbc
import pandas as pd





def db_connection():
    # await asyncio.sleep(10)
    conn =  pyodbc.connect(
    Trusted_Connection = "Yes",
    Driver = '{ODBC Driver 18 for SQL Server}',
    Server ="My_db_server",
    Database  = "test_database",
    Encrypt="no"
        )
       
    # cursor = conn.cursor()
    return conn
    

async def table_one(conn):
    await asyncio.sleep(12)
    sql_query_string = "SELECT * FROM test_database.dbo.Employee;"
    df = pd.read_sql_query( sql_query_string, conn)
    print(df)
    
async def table_two(conn):
    
    sql_query_string = "SELECT * FROM test_database.dbo.Department;"
    df = pd.read_sql_query( sql_query_string, conn)
    print(df)

async def dummy():
    print("this is the dummy function")
    
async def main():
    conn = db_connection()
    task1 = asyncio.create_task(table_one(conn))
    task2 = asyncio.create_task(table_two(conn))
    task3 = asyncio.create_task(dummy())
    print("calling database connection")
    
    
    await task2
    await task1
    await task3
    


asyncio.run(main())

注意:我知道在 pyodbc.connect() 前面添加 await 会导致错误,因为它不是异步函数,但我可以轻松等待主函数中的 db_connection() 函数函数以获得相同的异步功能。

python-3.x sql-server asynchronous pypyodbc
1个回答
0
投票

即使在异步函数中调用,对

conn = db_connection()
pd.read_sql_query
的调用也将同步执行。因此,在任务 2 完成之前,任务 1 和任务 3 不会执行。为了说明我在说什么:

import asyncio
import time
    
async def do_task1():
    print('start task 1')
    time.sleep(1)
    print('done task 1')
    
async def do_task2():
    print('start task 2')
    time.sleep(1)
    print('done task 2')
  
async def main():
    task1 = asyncio.create_task(do_task1())
    task2 = asyncio.create_task(do_task2())
   
    await task2
    await task1

start_time = time.time()
asyncio.run(main())
total_time = time.time() - start_time
print(total_time)

以下代码执行大约需要 2 秒。切换到使用 asyncio.sleep,代码现在可以在 1 秒内执行:

import asyncio
import time
    
async def do_task1():
    print('start task 1')
    await asyncio.sleep(1)
    print('done task 1')
    
async def do_task2():
    print('start task 2')
    await asyncio.sleep(1)
    print('done task 2')
  
async def main():
    task1 = asyncio.create_task(do_task1())
    task2 = asyncio.create_task(do_task2())
   
    await task2
    await task1

start_time = time.time()
asyncio.run(main())
total_time = time.time() - start_time
print(total_time)

代码可以这样简化:

import asyncio
import time
    
async def do_task1():
    print('start task 1')
    await asyncio.sleep(1)
    print('done task 1')
    
async def do_task2():
    print('start task 2')
    await asyncio.sleep(1)
    print('done task 2')
  
async def main():
    task1 = do_task1()
    task2 = do_task2()
    await asyncio.gather(task1, task2)

start_time = time.time()
asyncio.run(main())
total_time = time.time() - start_time
print(total_time)

使用 aioodbc 将使查询的执行异步,因此允许它们并行执行。您当前的代码将在执行每个查询时阻塞。

© www.soinside.com 2019 - 2024. All rights reserved.