Based on https://github.com/blender/blender/commit/780c0ea097444c3be60314dffd203c099720badb

diff --git source/blender/python/generic/py_capi_utils.c source/blender/python/generic/py_capi_utils.c
index 44293759672..2b2ca4acced 100644
--- source/blender/python/generic/py_capi_utils.c
+++ source/blender/python/generic/py_capi_utils.c
@@ -402,6 +402,7 @@ void PyC_StackSpit(void)
 void PyC_FileAndNum(const char **r_filename, int *r_lineno)
 {
   PyFrameObject *frame;
+  PyCodeObject *code;
 
   if (r_filename) {
     *r_filename = NULL;
@@ -410,13 +411,16 @@ void PyC_FileAndNum(const char **r_filename, int *r_lineno)
     *r_lineno = -1;
   }
 
-  if (!(frame = PyThreadState_GET()->frame)) {
+  if (!(frame = PyEval_GetFrame())) {
+    return;
+  }
+  if (!(code = PyFrame_GetCode(frame))) {
     return;
   }
 
   /* when executing a script */
   if (r_filename) {
-    *r_filename = PyUnicode_AsUTF8(frame->f_code->co_filename);
+    *r_filename = PyUnicode_AsUTF8(code->co_filename);
   }
 
   /* when executing a module */
diff --git source/blender/python/intern/bpy_driver.c source/blender/python/intern/bpy_driver.c
index 6c078e4228c..af5a04c60c6 100644
--- source/blender/python/intern/bpy_driver.c
+++ source/blender/python/intern/bpy_driver.c
@@ -276,6 +276,56 @@ static void pydriver_error(ChannelDriver *driver)
 #  define OK_OP(op) [op] = 1
 
 static const char secure_opcodes[255] = {
+#  if PY_VERSION_HEX >= 0x030b0000 /* Python 3.11 & newer. */
+
+    OK_OP(CACHE),
+    OK_OP(POP_TOP),
+    OK_OP(PUSH_NULL),
+    OK_OP(NOP),
+    OK_OP(UNARY_POSITIVE),
+    OK_OP(UNARY_NEGATIVE),
+    OK_OP(UNARY_NOT),
+    OK_OP(UNARY_INVERT),
+    OK_OP(BINARY_SUBSCR),
+    OK_OP(GET_LEN),
+    OK_OP(RETURN_VALUE),
+    OK_OP(SWAP),
+    OK_OP(BUILD_TUPLE),
+    OK_OP(BUILD_LIST),
+    OK_OP(BUILD_SET),
+    OK_OP(BUILD_MAP),
+    OK_OP(COMPARE_OP),
+    OK_OP(JUMP_FORWARD),
+    OK_OP(JUMP_IF_FALSE_OR_POP),
+    OK_OP(JUMP_IF_TRUE_OR_POP),
+    OK_OP(POP_JUMP_FORWARD_IF_FALSE),
+    OK_OP(POP_JUMP_FORWARD_IF_TRUE),
+    OK_OP(LOAD_GLOBAL),
+    OK_OP(IS_OP),
+    OK_OP(BINARY_OP),
+    OK_OP(LOAD_FAST),
+    OK_OP(STORE_FAST),
+    OK_OP(DELETE_FAST),
+    OK_OP(POP_JUMP_FORWARD_IF_NOT_NONE),
+    OK_OP(POP_JUMP_FORWARD_IF_NONE),
+    OK_OP(BUILD_SLICE),
+    OK_OP(LOAD_DEREF),
+    OK_OP(STORE_DEREF),
+    OK_OP(RESUME),
+    OK_OP(POP_JUMP_BACKWARD_IF_NOT_NONE),
+    OK_OP(POP_JUMP_BACKWARD_IF_NONE),
+    OK_OP(POP_JUMP_BACKWARD_IF_FALSE),
+    OK_OP(POP_JUMP_BACKWARD_IF_TRUE),
+
+    /* Special cases. */
+    OK_OP(LOAD_CONST), /* Ok because constants are accepted. */
+    OK_OP(LOAD_NAME),  /* Ok, because `PyCodeObject.names` is checked. */
+    OK_OP(CALL),       /* Ok, because we check its "name" before calling. */
+    OK_OP(KW_NAMES),   /* Ok, because it's used for calling functions with keyword arguments. */
+    OK_OP(PRECALL),    /* Ok, because it's used for calling. */
+
+#  else /* Python 3.10 and older. */
+
     OK_OP(POP_TOP),
     OK_OP(ROT_TWO),
     OK_OP(ROT_THREE),
@@ -338,6 +388,8 @@ static const char secure_opcodes[255] = {
     OK_OP(CALL_FUNCTION), /* ok, because we check its 'name' before calling */
     OK_OP(CALL_FUNCTION_KW),
     OK_OP(CALL_FUNCTION_EX),
+
+#  endif /* Python 3.10 and older. */
 };
 
 #  undef OK_OP
@@ -375,7 +427,15 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d
     const _Py_CODEUNIT *codestr;
     Py_ssize_t code_len;
 
-    PyBytes_AsStringAndSize(py_code->co_code, (char **)&codestr, &code_len);
+    PyObject *co_code;
+
+#  if PY_VERSION_HEX >= 0x030b0000 /* Python 3.11 & newer. */
+    co_code = py_code->_co_code;
+#  else
+    co_code = py_code->co_code;
+#  endif
+
+    PyBytes_AsStringAndSize(co_code, (char **)&codestr, &code_len);
     code_len /= sizeof(*codestr);
 
     for (Py_ssize_t i = 0; i < code_len; i++) {
diff --git source/blender/python/intern/bpy_interface.c source/blender/python/intern/bpy_interface.c
index 5f31e0bb74d..c07ea42c872 100644
--- source/blender/python/intern/bpy_interface.c
+++ source/blender/python/intern/bpy_interface.c
@@ -589,16 +589,17 @@ void BPY_python_use_system_env(void)
 void BPY_python_backtrace(FILE *fp)
 {
   fputs("\n# Python backtrace\n", fp);
-  PyThreadState *tstate = PyGILState_GetThisThreadState();
-  if (tstate != NULL && tstate->frame != NULL) {
-    PyFrameObject *frame = tstate->frame;
-    do {
-      const int line = PyCode_Addr2Line(frame->f_code, frame->f_lasti);
-      const char *filename = PyUnicode_AsUTF8(frame->f_code->co_filename);
-      const char *funcname = PyUnicode_AsUTF8(frame->f_code->co_name);
-      fprintf(fp, "  File \"%s\", line %d in %s\n", filename, line, funcname);
-    } while ((frame = frame->f_back));
+  PyFrameObject *frame;
+  if (!(frame = PyEval_GetFrame())) {
+    return;
   }
+  do {
+    PyCodeObject *code = PyFrame_GetCode(frame);
+    const int line = PyFrame_GetLineNumber(frame);
+    const char *filepath = PyUnicode_AsUTF8(code->co_filename);
+    const char *funcname = PyUnicode_AsUTF8(code->co_name);
+    fprintf(fp, "  File \"%s\", line %d in %s\n", filepath, line, funcname);
+  } while ((frame = PyFrame_GetBack(frame)));
 }
 
 void BPY_DECREF(void *pyob_ptr)
diff --git source/blender/python/intern/bpy_traceback.c source/blender/python/intern/bpy_traceback.c
index 00b414e027e..019dc38488f 100644
--- source/blender/python/intern/bpy_traceback.c
+++ source/blender/python/intern/bpy_traceback.c
@@ -34,7 +34,8 @@
 
 static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce)
 {
-  *coerce = PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename);
+  PyCodeObject *code = PyFrame_GetCode(tb->tb_frame);
+  *coerce = PyUnicode_EncodeFSDefault(code->co_filename);
   return PyBytes_AS_STRING(*coerce);
 }
 
