omnilib / aiosqlite

asyncio bridge to the standard sqlite3 module

Home Page:https://aiosqlite.omnilib.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Aiosqlite leaves thread hanging

raees-khan opened this issue · comments

class ProxyClass:
     def __init__(self):
         self._conn = None
         self._connected = False
    
    async def connect(self):
        self._conn = await aiosqlite.connect(':memory:')
        self._connected = True

    def close(self):
        await self._conn.close()
        self._connected = False
   
    def __getattr__(self, name):
        return getattr(self._conn, name)


async def run():
    db = ProxyClass()
    await db.connect()
   try:
        #perform some long running db updates
        #commit changes
   finally:
        await db.close()

I import this in a script and call run using asyncio.run(run()). It finishes but the program never exits because the thread does not get stopped and ctrl+c spits following.

^CException ignored in: <module 'threading' from '/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/threading.py'> Traceback (most recent call last): File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/threading.py", line 1448, in _shutdown lock.acquire() KeyboardInterrupt:

I can’t replicate this with the example code. Are you sure your “long running db updates” have actually completed before pressing ctrl-c? Can you provide more insight on what that long running functionality entails?

Hello
I have the same problem. But in my case its short select for two rows in result.

I have found that it happens when you have multiple connections (aka multiple threads).

import aiosqlite
import asyncio

class ProxyClass:
    def __init__(self):
        self._conn = None
        self._connected = False
    
    async def connect(self):
        self._conn = await aiosqlite.connect(':memory:')
        self._connected = True

    async def close(self):
        await self._conn.close()
        self._connected = False
   
    def __getattr__(self, name):
        return getattr(self._conn, name)
        

class DBRunner:
	
	def __init__(self):
		self._dbs = {
			"db1": ProxyClass(),
			"db2": ProxyClass()
		}
	
	async def init_dbs(self):
		await asyncio.gather(
			*[db.connect() for db in self._dbs.values()]
		)
	
	async def close_dbs(self):
		for db in self._dbs.values():
			await db.close()
	
	async def run(self, name):
		db = self._dbs[name]
		await db.execute("CREATE TABLE memview_v1 (X, Y)")
		await db.execute("INSERT INTO memview_v1 (X, Y) VALUES(1,2)")
		await db.commit()		
		


async def main():
	runner = DBRunner()
	try:
		await runner.init_dbs()
		await asyncio.gather(*[runner.run(name) for name in ('db1', 'db2')])
	finally:
		await runner.close_dbs()
		
asyncio.run(main())

for each connection a separate thread is created. The actual code makes thousands of inserts updates and deletes to disk based db connection, but I ensure to call db.close() of each db in my finally block. The program never really exits and the shell hangs and ctrl+c yields that output