@@ -350,13 +350,19 @@ void RegisterExceptions(const py::module &m) {
350350 auto io_exception = py::register_exception<PyIOException>(m, " IOException" , operational_error).ptr ();
351351 py::register_exception<PySerializationException>(m, " SerializationException" , operational_error);
352352
353- static py::exception<PyHTTPException> HTTP_EXCEPTION (m, " HTTPException" , io_exception);
354- const auto string_type = py::type::of (py::str ());
355- const auto Dict = py::module_::import (" typing" ).attr (" Dict" );
356- HTTP_EXCEPTION.attr (" __annotations__" ) =
357- py::dict (py::arg (" status_code" ) = py::type::of (py::int_ ()), py::arg (" body" ) = string_type,
358- py::arg (" reason" ) = string_type, py::arg (" headers" ) = Dict[py::make_tuple (string_type, string_type)]);
359- HTTP_EXCEPTION.doc () = " Thrown when an error occurs in the httpfs extension, or whilst downloading an extension." ;
353+ // Use a raw pointer to avoid destructor running after Python finalization.
354+ // The module holds a reference to the exception type, keeping it alive.
355+ static PyObject *HTTP_EXCEPTION = nullptr ;
356+ {
357+ auto http_exc = py::register_exception<PyHTTPException>(m, " HTTPException" , io_exception);
358+ HTTP_EXCEPTION = http_exc.ptr ();
359+ const auto string_type = py::type::of (py::str ());
360+ const auto Dict = py::module_::import (" typing" ).attr (" Dict" );
361+ http_exc.attr (" __annotations__" ) = py::dict (
362+ py::arg (" status_code" ) = py::type::of (py::int_ ()), py::arg (" body" ) = string_type,
363+ py::arg (" reason" ) = string_type, py::arg (" headers" ) = Dict[py::make_tuple (string_type, string_type)]);
364+ http_exc.doc () = " Thrown when an error occurs in the httpfs extension, or whilst downloading an extension." ;
365+ }
360366
361367 // IntegrityError
362368 auto integrity_error = py::register_exception<IntegrityError>(m, " IntegrityError" , db_error).ptr ();
@@ -388,7 +394,7 @@ void RegisterExceptions(const py::module &m) {
388394 } catch (const duckdb::Exception &ex) {
389395 duckdb::ErrorData error (ex);
390396 UnsetPythonException ();
391- PyThrowException (error, HTTP_EXCEPTION. ptr () );
397+ PyThrowException (error, HTTP_EXCEPTION);
392398 } catch (const py::builtin_exception &ex) {
393399 // These represent Python exceptions, we don't want to catch these
394400 throw ;
@@ -399,7 +405,7 @@ void RegisterExceptions(const py::module &m) {
399405 throw ;
400406 }
401407 UnsetPythonException ();
402- PyThrowException (error, HTTP_EXCEPTION. ptr () );
408+ PyThrowException (error, HTTP_EXCEPTION);
403409 }
404410 });
405411}
0 commit comments