-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SQLite connections are not closed when calling .close() in 3.11 #103837
Comments
I cannot reproduce this on 3.11.3 or 3.12.0a7 (macOS). |
I cannot reproduce with 3.11 on Ubuntu 22.04 either. Unless you have a more deterministic reproducer, I'm not sure what to do with this :( |
For me it fails on 3.11.3 (macOS). Running
|
This comment was marked as outdated.
This comment was marked as outdated.
What's the output of this script? import sqlite3
cx = sqlite3.connect(":memory:")
for row in cx.execute("pragma compile_options"):
print(row[0]) |
This comment was marked as outdated.
This comment was marked as outdated.
All right, I can reproduce this now. Looking into it. |
Yeah, I can confirm this is caused the cyclic reference between the statement cache and the connection. I'm not sure what's the best solution for this ATM. |
@vstinner, do you have tips for how we can handle this better? Some background: In f461a7f, I tore out the |
From the Python user perspective: we are calling |
|
Sorry, I was imprecise when quoting. As a user, indeed, I do not care when an object is collected. I do care that the resource that object holds is released. To me, this issue feels as if calling Are there any other workarounds besides calling |
In general, it's a bad idea to rely on the GC to release resources. This assumption is wrong on PyPy which has a different GC implementation. I strongly prefer explicit resource management. Usually, a close() method should be called. And a ResourceWarning is emitted if a resource is not released explicitly. In the first example, it's unclear to me when and how write_value() connection is supposed to be closed. For me, a ResourceWarning should be emitted, and the connection should be closed explicitly. |
We're asserting that the EDIT: I misremembered; we're using Footnotes
|
Quick update after #103837 (comment): Changing the underlying SQLite C API from |
Ok. I think you can close this issue. The documentation clearly spells out that what we're doing is based on incorrect assumptions. I assumed that the context manager closed the connection, but it only manages a transaction. As @vstinner points out, we are not calling If I change the sample code to this, then the test passes:
Thanks and sorry for the 'panic'. |
I did not spot the missing close! That explains the problem, indeed 😃 I still think we should consider changing the underlying API so we can emit a resource warning if close failed. |
Also, check out contextlib.closing, if you did not know about that one already :) |
In our application we do have a context manager that closes the connection in a But obviously there is a place where we're not using that context manager in the proper way. We did have some errors in the past we could not explain on application startup where a database was busy during database migrations. That's also the place were we use that shared memory trick with in-memory databases for during tests. More work needed on our side. Thanks again. |
In the Python developer mode, FileIO.close() logs an unraisable exception on error. It's only in developer mode to avoid any backward compatibilty issue, but I always want to always log this unraisable exception. ResourceWarning is more if the user didn't call close() explicitly (which is a different case). |
IMO sqlite3 should be modified to emit a ResourceWarning. Currently, no ResourceWarning is emitted when a connection is not closed explicitly:
|
Yes, I support this, as stated in #103837 (comment) |
Oh ok. I was just confused by "if close failed" in your statement. |
Yeah, I got too side tracked to see the real issue. |
See gh-108015 |
Bug report
In our tests we are using in-memory SQLite databases with a shared cache. This makes it possible to create multiple connections with the same connection string and see the same data, as recommended in In-Memory Databases. After updating from Python 3.10 to 3.11 our tests started failing.
The minimal reproduction case:
This works in 3.10 (and worked in 3.8 and 3.9), but fails in 3.11:
The SQLite documentations includes:
We used a workaround mentioned in #97641 for now (calling
gc.collect()
).I opened a new issue, since that one looks similar, but is Windows specific, while this one happens on Linux as well.
Your environment
The text was updated successfully, but these errors were encountered: