当前位置: 首页 > news >正文

Python运行时环境

1.1概念

程序运行只有栈帧不够,还要有进程与线程

Python在初始化时会创建一个主线程,所以其运行时环境中存在一个主线程,可以有多个线程

Python实现了对多线程的支持,而且一个线程就是操作系统上的一个原生线程

Python中所有线程都使用虚拟机(软CPU)来完成计算工作

某一个PyFrameObject就是执行环境,一整个为执行环境。

注:线程切换之前要保存关于当前线程的信息。

1.2 线程状态信息的抽象

通过PyThreadState对象实现,所以可以将该对象视为线程本身的抽象

typedef struct _ts PyThreadState;
struct _ts {PyThreadState *prev;PyThreadState *next;PyInterpreterState *interp;struct {/* Has been initialized to a safe state.In order to be effective, this must be set to 0 during or rightafter allocation. */unsigned int initialized:1;/* Has been bound to an OS thread. */unsigned int bound:1;/* Has been unbound from its OS thread. */unsigned int unbound:1;/* Has been bound aa current for the GILState API. */unsigned int bound_gilstate:1;/* Currently in use (maybe holds the GIL). */unsigned int active:1;/* various stages of finalization */unsigned int finalizing:1;unsigned int cleared:1;unsigned int finalized:1;/* padding to align to 4 bytes */unsigned int :24;} _status;int py_recursion_remaining;int py_recursion_limit;int c_recursion_remaining;int recursion_headroom; /* Allow 50 more calls to handle any errors. *//* 'tracing' keeps track of the execution depth when tracing/profiling.This is to prevent the actual trace/profile code from being recorded inthe trace/profile. */int tracing;int what_event; /* The event currently being monitored, if any. *//* Pointer to current _PyCFrame in the C stack frame of the currently,* or most recently, executing _PyEval_EvalFrameDefault. */_PyCFrame *cframe;Py_tracefunc c_profilefunc;Py_tracefunc c_tracefunc;PyObject *c_profileobj;PyObject *c_traceobj;/* The exception currently being raised */PyObject *current_exception;/* Pointer to the top of the exception stack for the exceptions* we may be currently handling.  (See _PyErr_StackItem above.)* This is never NULL. */_PyErr_StackItem *exc_info;PyObject *dict;  /* Stores per-thread state */int gilstate_counter;PyObject *async_exc; /* Asynchronous exception to raise */unsigned long thread_id; /* Thread id where this tstate was created *//* Native thread id where this tstate was created. This will be 0 except on* those platforms that have the notion of native thread id, for which the* macro PY_HAVE_THREAD_NATIVE_ID is then defined.*/unsigned long native_thread_id;struct _py_trashcan trash;/* Called when a thread state is deleted normally, but not when it* is destroyed after fork().* Pain:  to prevent rare but fatal shutdown errors (issue 18808),* Thread.join() must wait for the join'ed thread's tstate to be unlinked* from the tstate chain.  That happens at the end of a thread's life,* in pystate.c.* The obvious way doesn't quite work:  create a lock which the tstate* unlinking code releases, and have Thread.join() wait to acquire that* lock.  The problem is that we _are_ at the end of the thread's life:* if the thread holds the last reference to the lock, decref'ing the* lock will delete the lock, and that may trigger arbitrary Python code* if there's a weakref, with a callback, to the lock.  But by this time* _PyRuntime.gilstate.tstate_current is already NULL, so only the simplest* of C code can be allowed to run (in particular it must not be possible to* release the GIL).* So instead of holding the lock directly, the tstate holds a weakref to* the lock:  that's the value of on_delete_data below.  Decref'ing a* weakref is harmless.* on_delete points to _threadmodule.c's static release_sentinel() function.* After the tstate is unlinked, release_sentinel is called with the* weakref-to-lock (on_delete_data) argument, and release_sentinel releases* the indirectly held lock.*/void (*on_delete)(void *);void *on_delete_data;int coroutine_origin_tracking_depth;PyObject *async_gen_firstiter;PyObject *async_gen_finalizer;PyObject *context;uint64_t context_ver;/* Unique thread state id. */uint64_t id;_PyStackChunk *datastack_chunk;PyObject **datastack_top;PyObject **datastack_limit;/* XXX signal handlers should also be here *//* The following fields are here to avoid allocation during init.The data is exposed through PyThreadState pointer fields.These fields should not be accessed directly outside of init.This is indicated by an underscore prefix on the field names.All other PyInterpreterState pointer fields are populated whenneeded and default to NULL.*/// Note some fields do not have a leading underscore for backward// compatibility.  See https://bugs.python.org/issue45953#msg412046./* The thread's exception stack entry.  (Always the last entry.) */_PyErr_StackItem exc_state;/* The bottom-most frame on the stack. */_PyCFrame root_cframe;
};

1.3 进程的抽象

允许有多个进程(Interpreter)存在,但通常只有一个Interpreter,这个Interpreter维护了一个或多个PyThreadState对象。

通过PyInterpreterState对象实现

typedef struct _is PyInterpreterState;.
struct _is {PyInterpreterState *next;int64_t id;int64_t id_refcount;int requires_idref;PyThread_type_lock id_mutex;/* Has been initialized to a safe state.In order to be effective, this must be set to 0 during or rightafter allocation. */int _initialized;int finalizing;uint64_t monitoring_version;uint64_t last_restart_version;struct pythreads {uint64_t next_unique_id;/* The linked list of threads, newest first. */PyThreadState *head;/* Used in Modules/_threadmodule.c. */long count;/* Support for runtime thread stack size tuning.A value of 0 means using the platform's default stack sizeor the size specified by the THREAD_STACK_SIZE macro. *//* Used in Python/thread.c. */size_t stacksize;} threads;/* Reference to the _PyRuntime global variable. This field existsto not have to pass runtime in addition to tstate to a function.Get runtime from tstate: tstate->interp->runtime. */struct pyruntimestate *runtime;/* Set by Py_EndInterpreter().Use _PyInterpreterState_GetFinalizing()and _PyInterpreterState_SetFinalizing()to access it, don't access it directly. */_Py_atomic_address _finalizing;struct _gc_runtime_state gc;/* The following fields are here to avoid allocation during init.The data is exposed through PyInterpreterState pointer fields.These fields should not be accessed directly outside of init.All other PyInterpreterState pointer fields are populated whenneeded and default to NULL.For now there are some exceptions to that rule, which requireallocation during init.  These will be addressed on a case-by-casebasis.  Also see _PyRuntimeState regarding the various mutex fields.*/// Dictionary of the sys modulePyObject *sysdict;// Dictionary of the builtins modulePyObject *builtins;struct _ceval_state ceval;struct _import_state imports;/* The per-interpreter GIL, which might not be used. */struct _gil_runtime_state _gil;/* ---------- IMPORTANT ---------------------------The fields above this line are declared as early aspossible to facilitate out-of-process observabilitytools. */PyObject *codec_search_path;PyObject *codec_search_cache;PyObject *codec_error_registry;int codecs_initialized;PyConfig config;unsigned long feature_flags;PyObject *dict;  /* Stores per-interpreter state */PyObject *sysdict_copy;PyObject *builtins_copy;// Initialized to _PyEval_EvalFrameDefault()._PyFrameEvalFunction eval_frame;PyFunction_WatchCallback func_watchers[FUNC_MAX_WATCHERS];// One bit is set for each non-NULL entry in func_watchersuint8_t active_func_watchers;Py_ssize_t co_extra_user_count;freefunc co_extra_freefuncs[MAX_CO_EXTRA_USERS];#ifdef HAVE_FORKPyObject *before_forkers;PyObject *after_forkers_parent;PyObject *after_forkers_child;
#endifstruct _warnings_runtime_state warnings;struct atexit_state atexit;struct _obmalloc_state obmalloc;PyObject *audit_hooks;PyType_WatchCallback type_watchers[TYPE_MAX_WATCHERS];PyCode_WatchCallback code_watchers[CODE_MAX_WATCHERS];// One bit is set for each non-NULL entry in code_watchersuint8_t active_code_watchers;struct _py_object_state object_state;struct _Py_unicode_state unicode;struct _Py_float_state float_state;struct _Py_long_state long_state;struct _dtoa_state dtoa;struct _py_func_state func_state;/* Using a cache is very effective since typically only a single slice iscreated and then deleted again. */PySliceObject *slice_cache;struct _Py_tuple_state tuple;struct _Py_list_state list;struct _Py_dict_state dict_state;struct _Py_async_gen_state async_gen;struct _Py_context_state context;struct _Py_exc_state exc_state;struct ast_state ast;struct types_state types;struct callable_cache callable_cache;PyCodeObject *interpreter_trampoline;_Py_GlobalMonitors monitors;bool f_opcode_trace_set;bool sys_profile_initialized;bool sys_trace_initialized;Py_ssize_t sys_profiling_threads; /* Count of threads with c_profilefunc set */Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][_PY_MONITORING_EVENTS];PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS];struct _Py_interp_cached_objects cached_objects;struct _Py_interp_static_objects static_objects;// XXX Remove this field once we have a tp_* slot.struct _xidregistry xidregistry;/* The thread currently executing in the __main__ module, if any. */PyThreadState *threads_main;/* The ID of the OS thread in which we are finalizing.We use _Py_atomic_address instead of adding a new _Py_atomic_ulong. */_Py_atomic_address _finalizing_id;/* the initial PyInterpreterState.threads.head */PyThreadState _initial_thread;
};

1.4 建立新的PyFrameObject对象

PyFrameObject*
PyFrame_New(PyThreadState *tstate, PyCodeObject *code,PyObject *globals, PyObject *locals)
{PyObject *builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed refif (builtins == NULL) {return NULL;}PyFrameConstructor desc = {.fc_globals = globals,.fc_builtins = builtins,.fc_name = code->co_name,.fc_qualname = code->co_name,.fc_code = (PyObject *)code,.fc_defaults = NULL,.fc_kwdefaults = NULL,.fc_closure = NULL};PyFunctionObject *func = _PyFunction_FromConstructor(&desc);if (func == NULL) {return NULL;}PyFrameObject *f = _PyFrame_New_NoTrack(code);if (f == NULL) {Py_DECREF(func);return NULL;}init_frame((_PyInterpreterFrame *)f->_f_frame_data, func, locals);f->f_frame = (_PyInterpreterFrame *)f->_f_frame_data;f->f_frame->owner = FRAME_OWNED_BY_FRAME_OBJECT;// This frame needs to be "complete", so pretend that the first RESUME ran:f->f_frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable;assert(!_PyFrame_IsIncomplete(f->f_frame));Py_DECREF(func);_PyObject_GC_TRACK(f);return f;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 读软件开发安全之道:概念、设计与实施13Web安全
  • 【设计模式】单例模式、工厂模式、策略模式、观察者模式、装饰器模式
  • 新手小白Ubuntu18.04超详细安装教程
  • Python进阶03-闭包和装饰器
  • PyTorch 基础学习(14)- 归一化
  • 二极管、电阻、电容、电感的种类及作用
  • PHP EOF(heredoc) 速成技巧
  • 如何借助前端表格控件实现软硬一体化数据管理平台
  • 深度学习速通系列:贝叶思SVM
  • spring boot 根据实体类生成表
  • 背包习题
  • CSS 中高度 100%和高度 100vh 有什么区别
  • 第二证券:静态市盈率与动态市盈率有什么区别?
  • 区块链(币圈)常用网址大全
  • STM32F411 标准库硬件SPI (硬件NSS/CS)驱动st7735--1.8寸TFT显示屏
  • 03Go 类型总结
  • Angular6错误 Service: No provider for Renderer2
  • gulp 教程
  • MobX
  • OSS Web直传 (文件图片)
  • Sass Day-01
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 三分钟教你同步 Visual Studio Code 设置
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 微信公众号开发小记——5.python微信红包
  • 《天龙八部3D》Unity技术方案揭秘
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • (1)无线电失控保护(二)
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (function(){})()的分步解析
  • (solr系列:一)使用tomcat部署solr服务
  • (笔试题)合法字符串
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • (转)EXC_BREAKPOINT僵尸错误
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .NET Micro Framework 4.2 beta 源码探析
  • .net6 core Worker Service项目,使用Exchange Web Services (EWS) 分页获取电子邮件收件箱列表,邮件信息字段
  • .NET8使用VS2022打包Docker镜像
  • .net反混淆脱壳工具de4dot的使用
  • .NET应用UI框架DevExpress XAF v24.1 - 可用性进一步增强
  • @DataRedisTest测试redis从未如此丝滑
  • @font-face 用字体画图标
  • @serverendpoint注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • @Value获取值和@ConfigurationProperties获取值用法及比较(springboot)
  • [120_移动开发Android]008_android开发之Pull操作xml文件