python3.5源码分析-启动与虚拟机

2023-10-27

Python3源码分析

本文环境python3.5.2。
参考书籍<<Python源码剖析>>
python官网

Python3启动流程概述

本文基于python3分析其基本的运行过程。作为一门动态语言,python脚本在运行的过程中,实现了编译文件并执行编译文件的过程,这一过程都是基于c语言实现,首先开始介绍一下python3的基本信息。

Python3源码结构

在官网下载python3.5.2后,根据官网的文档目录介绍,主要目录的信息如下:

python文档组织结构

Doc目录主要是官方文档的说明。

Include目录主要包括了Python的运行的头文件。

Lib目录主要包括了用Python实现的标准库。

Objects目录包括了内建对象。

Parser目录包括了python编译相关代码,将python文件编译生成语法树等相关工作。

Programs目录主要包括了python的入口函数。

Python目录主要包括了Python动态运行时执行的代码,里面包括编译、字节码解释器等工作。

Python的启动流程

根据官网文档目录介绍,启动的时候是运行Python的脚本,Python启动是由Programs下的python.c文件中的main函数开始执行,根据平台的不同选择执行不同类型的main函数,在此已Linux为例;

int
main(int argc, char **argv)
{
     ...
    res = Py_Main(argc, argv_copy);
     ...
    return res;
}

该函数主要就是执行了Py_Main函数,并将该函数的执行结果返回。

继续查看Py_Main函数的执行,在位于Modules/main.c中找到Py_Main函数,

int
Py_Main(int argc, wchar_t **argv)
{
    ...
    Py_Initialize();                              // 初始化
    ...
    {
        ...
        if (sts == -1)
            sts = run_file(fp, filename, &cf);    // 执行python脚本
    }
    ...
    Py_Finalize();                                // 释放相关资源
    ...
    return sts;                                   // 返回执行结果
}

由此可看出,在调用初始化函数Py_Initialize之后,就会执行run_file方法,当Python脚本执行完成后,就调用Py_Finalize释放相关资源。分别来查看这些函数的执行。

Py_Initialize初始化函数

该函数位于Python/pylifecycle.c中,

void
Py_InitializeEx(int install_sigs)
{
    _Py_InitializeEx_Private(install_sigs, 1);
}

void
Py_Initialize(void)
{
    Py_InitializeEx(1);
}

直接调用了_Py_InitializeEx_Private方法,并且传入了两个都为1的参数,

void
_Py_InitializeEx_Private(int install_sigs, int install_importlib)
{
    ...
    _PyRandom_Init();                                                // random模块初始化

    interp = PyInterpreterState_New();                               // 初始化解释器
    if (interp == NULL)
        Py_FatalError("Py_Initialize: can't make first interpreter");

    tstate = PyThreadState_New(interp);                              // 初始化线程
    if (tstate == NULL)
        Py_FatalError("Py_Initialize: can't make first thread");
    (void) PyThreadState_Swap(tstate);                               // 设置tstate为当前运行线程

#ifdef WITH_THREAD
    /* We can't call _PyEval_FiniThreads() in Py_Finalize because
       destroying the GIL might fail when it is being referenced from
       another running thread (see issue #9901).
       Instead we destroy the previously created GIL here, which ensures
       that we can call Py_Initialize / Py_Finalize multiple times. */
    _PyEval_FiniThreads();                                           // 如果脚本中是多线程运行则创建gil锁

    /* Auto-thread-state API */
    _PyGILState_Init(interp, tstate);
#endif /* WITH_THREAD */

    _Py_ReadyTypes();                                                // 初始化所有类型,如long,list等
    ...

    interp->modules = PyDict_New();                                 // 设置解释器的modules为新建的Dict类型
    if (interp->modules == NULL)                                    // 如果字典没有生成成功则报错
        Py_FatalError("Py_Initialize: can't make modules dictionary");

    /* Init Unicode implementation; relies on the codec registry */
    if (_PyUnicode_Init() < 0)
        Py_FatalError("Py_Initialize: can't initialize unicode");
    if (_PyStructSequence_Init() < 0)
        Py_FatalError("Py_Initialize: can't initialize structseq");

    bimod = _PyBuiltin_Init();                                      // 内建对象的初始化,如map,None,True等
    if (bimod == NULL)
        Py_FatalError("Py_Initialize: can't initialize builtins modules");
    _PyImport_FixupBuiltin(bimod, "builtins");                      // 设置builtins为初始化后的mod
    interp->builtins = PyModule_GetDict(bimod);                     // 设置解释器的builtins字段为初始化后的内建对象
    if (interp->builtins == NULL)
        Py_FatalError("Py_Initialize: can't initialize builtins dict");
    Py_INCREF(interp->builtins);                                    // 增加内建对象的引用

    /* initialize builtin exceptions */
    _PyExc_Init(bimod);                                             // 导入内建的错误类型,如BaseException,Exception等

    sysmod = _PySys_Init();                                         // 初始化sys模块
    if (sysmod == NULL)
        Py_FatalError("Py_Initialize: can't initialize sys");
    interp->sysdict = PyModule_GetDict(sysmod);                     // 设置解释器的sys模块
    if (interp->sysdict == NULL)
        Py_FatalError("Py_Initialize: can't initialize sys dict");
    Py_INCREF(interp->sysdict);
    _PyImport_FixupBuiltin(sysmod, "sys");                          // 将初始化的sysmod设置成模块sys
    PySys_SetPath(Py_GetPath());                                    // 设置导入路径
    PyDict_SetItemString(interp->sysdict, "modules",
                         interp->modules);

    ...

    initmain(interp); /* Module __main__ */                         // 创建主main
    ...
}

该函数主要进行了相关类型的初始化,并初始化了解释器,初始化了线程对象,并设置了相关的内建mod等初始化工作。当初始化工作完成后,就调用了run_file来解释并执行脚本。

run_file编译并执行

该函数位于main.c文件中,

static int
run_file(FILE *fp, const wchar_t *filename, PyCompilerFlags *p_cf)
{
    ...
    run = PyRun_AnyFileExFlags(fp, filename_str, filename != NULL, p_cf);   // 解释执行
    ...
    return run != 0;
}

真正调用了位于Python/pythonrun.c中的PyRun_AnyFileExFlags方法来解释执行,

int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
                     PyCompilerFlags *flags)
{
    if (filename == NULL)
        filename = "???";
    if (Py_FdIsInteractive(fp, filename)) {                                 // 是否是交互模式
        int err = PyRun_InteractiveLoopFlags(fp, filename, flags); 
        if (closeit)
            fclose(fp);
        return err;
    }
    else
        return PyRun_SimpleFileExFlags(fp, filename, closeit, flags);       // 执行脚本
}

此处讨论的是脚本模式,此时就会进入PyRun_SimpleFileExFlags函数执行,

int
PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
                        PyCompilerFlags *flags)
{
    ...
    else {
        ...
        v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d,
                              closeit, flags);                      // 在没有pyc的情况下执行
    }
    ...
}

此时就调用了PyRun_FileExFlags函数进行执行,

PyObject *
PyRun_FileExFlags(FILE *fp, const char *filename_str, int start, PyObject *globals,
                  PyObject *locals, int closeit, PyCompilerFlags *flags)
{
    ...

    mod = PyParser_ASTFromFileObject(fp, filename, NULL, start, 0, 0,
                                     flags, NULL, arena);                   // 解析传入的脚本,解析成AST
    ... 
    ret = run_mod(mod, filename, globals, locals, flags, arena);            // 将AST编译成字节码然后启动字节码解释器执行编译结果

    ...
}

查看run_mod函数,

static PyObject *
run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals,
            PyCompilerFlags *flags, PyArena *arena)
{
    ...
    co = PyAST_CompileObject(mod, filename, flags, -1, arena);      // 将AST编译成字节码
    ... 
    v = PyEval_EvalCode((PyObject*)co, globals, locals);            // 解释执行编译的字节码
    ...
}

再将AST转换为字节码后,调用了PyEval_EvalCode来执行字节码,查看位于Python/ceval.c中的该函数,

PyObject *
PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)
{
    return PyEval_EvalCodeEx(co,
                      globals, locals,
                      (PyObject **)NULL, 0,
                      (PyObject **)NULL, 0,
                      (PyObject **)NULL, 0,
                      NULL, NULL);
}
...

PyObject *
PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
           PyObject **args, int argcount, PyObject **kws, int kwcount,
           PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
{
    return _PyEval_EvalCodeWithName(_co, globals, locals,
                                    args, argcount, kws, kwcount,
                                    defs, defcount, kwdefs, closure,
                                    NULL, NULL);
}

直接调用了_PyEval_EvalCodeWithName函数来执行,

static PyObject *
_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
           PyObject **args, int argcount, PyObject **kws, int kwcount,
           PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure,
           PyObject *name, PyObject *qualname)
{
    ...

    retval = PyEval_EvalFrameEx(f,0);

    ...
}

最终调用了PyEval_EvalFrameEx来执行,该函数就是字节码解释器,实现方式就是一个for循序依次执行字节码,然后调用相关函数去执行,解释出来的脚本,然后返回执行结果。

至此,run_file的大致执行流程如上。

Python3虚拟机框架

通过分析Python的大致执行流程,有了初步了解Python是经历了多少步骤然后调用了哪些函数来进行执行。现在继续分析一下Python的虚拟机框架是如何来实现Python脚本的执行的。

首先我们编写一个简单的Python脚本;

def show():
    print("show")

def foo():
    print("foo")

show()
foo()

在终端命令行中,直接输入:

python -m dis test.py

终端上打印出该脚本的字节码,如下:

  1           0 LOAD_CONST               0 (<code object show at 0x10f2cc8a0, file "test.py", line 1>)
              3 LOAD_CONST               1 ('show')
              6 MAKE_FUNCTION            0
              9 STORE_NAME               0 (show)

  4          12 LOAD_CONST               2 (<code object foo at 0x10f2ccd20, file "test.py", line 4>)
             15 LOAD_CONST               3 ('foo')
             18 MAKE_FUNCTION            0
             21 STORE_NAME               1 (foo)

  7          24 LOAD_NAME                0 (show)
             27 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
             30 POP_TOP

  8          31 LOAD_NAME                1 (foo)
             34 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
             37 POP_TOP
             38 LOAD_CONST               4 (None)
             41 RETURN_VALUE

从中可以看到两个函数foo和show生成了两个code对象,code对象是什么作用呢?

Python的code对象

在Python的编译过程中,一个代码块就对应一个code对象,那Python如何定义一个代码块呢?当编译过程中遇到一个新的命令空间或者作用域时就生成一个code对象,即类或函数都是一个代码块,一个code的类型结构就是PyCodeObject;

typedef struct {
    PyObject_HEAD
    int co_argcount;        /* #arguments, except *args */      // 位置参数的个数
    int co_kwonlyargcount;  /* #keyword only arguments */ 
    int co_nlocals;     /* #local variables */                  // 局部变量个数
    int co_stacksize;       /* #entries needed for evaluation stack */  // 栈大小
    int co_flags;       /* CO_..., see below */
    PyObject *co_code;      /* instruction opcodes */           // 对应编译的字节码
    PyObject *co_consts;    /* list (constants used) */         // 保存所有的常量  列表类型
    PyObject *co_names;     /* list of strings (names used) */  // 保存所有的符号
    PyObject *co_varnames;  /* tuple of strings (local variable names) */  // 局部变量名集合
    PyObject *co_freevars;  /* tuple of strings (free variable names) */   // 闭包中的常量
    PyObject *co_cellvars;      /* tuple of strings (cell variable names) */ // 嵌套函数引用的局部变量
    /* The rest aren't used in either hash or comparisons, except for
       co_name (used in both) and co_firstlineno (used only in
       comparisons).  This is done to preserve the name and line number
       for tracebacks and debuggers; otherwise, constant de-duplication
       would collapse identical functions/lambdas defined on different lines.
    */
    unsigned char *co_cell2arg; /* Maps cell vars which are arguments. */
    PyObject *co_filename;  /* unicode (where it was loaded from) */        // 文件名
    PyObject *co_name;      /* unicode (name, for reference) */        
    int co_firstlineno;     /* first source line number */                  // 第一行源码行数
    PyObject *co_lnotab;    /* string (encoding addr<->lineno mapping) See
                   Objects/lnotab_notes.txt for details. */
    void *co_zombieframe;     /* for optimization only (see frameobject.c) */ 
    PyObject *co_weakreflist;   /* to support weakrefs to code objects */   // 弱引用
} PyCodeObject;

至此,可知脚本编译生成的字节码都存放在co_code中,其他属性字段都是存放了code在编译过程中保存的相关信息,这就是这个code对象在字节码解释器中运行时需要的局部变量,变量名等都是从code的相关字段中取值,有了PyCodeObject对象后,是如何在Python中被执行的呢?此时还需要将PyCodeObject对象转换成PyFrameObject对象。

Python的frame对象

在Python字节码执行的一级,会将PyCodeObject对象包装成PyFrameObject,一个PyCodeObject对应一个PyFrameObject对象,由此可知,test.py中存在三个PyFrameObject对象,除了show和foo外,还有一个是整个脚本的字节码所对应的PyFrameObject对象。

typedef struct _frame {
    PyObject_VAR_HEAD
    struct _frame *f_back;      /* previous frame, or NULL */            // 上一个栈帧对象
    PyCodeObject *f_code;       /* code segment */                       // 对应的code对象
    PyObject *f_builtins;       /* builtin symbol table (PyDictObject) */ // 内建对象
    PyObject *f_globals;        /* global symbol table (PyDictObject) */  // 全局名称空间
    PyObject *f_locals;         /* local symbol table (any mapping) */    // 本地名称空间
    PyObject **f_valuestack;    /* points after the last local */         // 栈低
    /* Next free slot in f_valuestack.  Frame creation sets to f_valuestack.
       Frame evaluation usually NULLs it, but a frame that yields sets it
       to the current stack top. */
    PyObject **f_stacktop;                                                // 栈顶
    ...

    int f_lasti;                /* Last instruction if called */          // 上一条执行命令
    /* Call PyFrame_GetLineNumber() instead of reading this field
       directly.  As of 2.3 f_lineno is only valid when tracing is
       active (i.e. when f_trace is set).  At other times we use
       PyCode_Addr2Line to calculate the line from the current
       bytecode index. */
    int f_lineno;               /* Current line number */                 // 当前行数
    int f_iblock;               /* index in f_blockstack */
    char f_executing;           /* whether the frame is still executing */
    PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
    PyObject *f_localsplus[1];  /* locals+stack, dynamically sized */     // 动态内存
} PyFrameObject;

由此可知,多个code对象就对应多个PyFrameObject对象,每一个栈帧都是像函数调用那样嵌套调用执行,此时继续分析Frame对象是如何Python的运行环境中执行。

Python3运行时环境

Python在运行的初始化阶段,在_Py_InitializeEx_Private函数中初始化了interp和tstate;

interp = PyInterpreterState_New();
if (interp == NULL)
    Py_FatalError("Py_Initialize: can't make first interpreter");

tstate = PyThreadState_New(interp);
if (tstate == NULL)
    Py_FatalError("Py_Initialize: can't make first thread");

由此可知,interp对应的就是一个解释器对象,tstate对应在Python中就是一个线程对象,这两者是如何推动Python的执行呢?

typedef struct _is {

    struct _is *next;                           // 下一个解释器对象
    struct _ts *tstate_head;                    // 线程对象

    PyObject *modules;                          // 模块的列表
    PyObject *modules_by_index;                 
    PyObject *sysdict;                          // 系统模块列表
    PyObject *builtins;                         // 内建对象列表
    PyObject *importlib;                        // 导入模块的函数

    PyObject *codec_search_path;                
    PyObject *codec_search_cache;
    PyObject *codec_error_registry;
    int codecs_initialized;
    int fscodec_initialized;

#ifdef HAVE_DLOPEN
    int dlopenflags;
#endif
#ifdef WITH_TSC
    int tscdump;
#endif

    PyObject *builtins_copy;                    // 内建对象副本
} PyInterpreterState;

由PyInterpreterState定义可以看出,解释器对象提供基本的内建对象和模块的数据,再来查看PyThreadState对象的定义;

typedef struct _ts {
    /* See Python/ceval.c for comments explaining most fields */

    struct _ts *prev;                                       // 上一个线程对象
    struct _ts *next;                                       // 下一个线程对象
    PyInterpreterState *interp;                             // 依赖的解释器对象

    struct _frame *frame;                                   // 当前执行的帧
    ...
    long thread_id; /* Thread id where this tstate was created */  // 线程id
    ...

} PyThreadState;

主要定义了上下线程对象,当前锁对应的解释器对象,和当前正在执行的栈帧。此时的栈帧就是将PyCodeObject生成的栈帧,在Python的启动阶段的时候会调用_PyEval_EvalCodeWithName函数,该函数中就是调用PyFrame_New函数生成新的执行栈帧;

    static PyObject *
_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
           PyObject **args, int argcount, PyObject **kws, int kwcount,
           PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure,
           PyObject *name, PyObject *qualname)
{   
    ...
    f = PyFrame_New(tstate, co, globals, locals);
    ...
    retval = PyEval_EvalFrameEx(f,0);
    ...
}

此时就进入字节码解释器解释执行,当执行到另一个PyCodeObject对象时,就调用PyFrame_New生成一个对应的frame调用字节码解释器继续执行。该生成过程位于fast_function函数中,后文会对其进行详细分析。至此Python运行的大概原理与执行的方式基本分析完毕。

总结

Python的运行过程图可归纳如下所示,

python运行时架构图

本文只是简单的分析了启动过程和Python的一个大致的执行过程,其中细节或有疏漏错误的地方请批评指正,具体详细的过程如有兴趣可自行调试分析。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python3.5源码分析-启动与虚拟机 的相关文章

  • pandas Wide_to_long 后缀参数

    我对在 pandas 中使用 Wide to long 时的参数有疑问 有一个参数叫suffix我不明白 在文档中它说 后缀 str 默认 d 捕获所需后缀的正则表达式 d 捕获数字后缀 没有数字的后缀可以用否定字符类 D 指定 您还可以进
  • 组和平均 NumPy 矩阵

    假设我有一个任意的 numpy 矩阵 如下所示 arr 6 0 12 0 1 0 7 0 9 0 1 0 8 0 7 0 1 0 4 0 3 0 2 0 6 0 1 0 2 0 2 0 5 0 2 0 9 0 4 0 3 0 2 0 1 0
  • 无法使用 BeautifulSoup 和 Requests 抓取下拉菜单

    我想抓取百年灵网站上的产品页面以获取各种信息 示例页面 https www breitling com gb en watches navitimer b01 chronograph 46 AB0127211C1A1 https www b
  • Tipfy:如何在模板中显示blob?

    鉴于在 gae 上使用tipfy http www tipfy org python 以下模型 greeting avatar db Blob avatar 显示 blob 此处为图像 的模板标签是什么 在这种情况下 斑点是一个图像 这很棒
  • 对于相同的查询,MySQL Workbench 比 Python 快得多

    MySQL Workbench 中的以下查询需要 0 156 秒才能完成 SELECT date time minute price id FROM minute prices WHERE contract id 673 AND TIMES
  • 按多个键分组并对字典列表的值进行汇总/平均值

    在Python中按多个键进行分组并对字典列表进行汇总 平均值的最Pythonic方法是什么 假设我有一个字典列表 如下所示 input dept 001 sku foo transId uniqueId1 qty 100 dept 001
  • 在 Linux 上的 Python 中使用受密码保护的 Excel 工作表

    问题很简单 我每周都会收到一堆受密码保护的 Excel 文件 我必须解析它们并使用 Python 将某些部分写入新文件 我得到了文件的密码 当在 Windows 上完成此操作时 处理起来很简单 我只需导入 win32com 并使用 clie
  • 在 iPython/pandas 中绘制多条线会生成多个图

    我试图了解 matplotlib 的状态机模型 但在尝试在单个图上绘制多条线时遇到错误 据我了解 以下代码应该生成包含两行的单个图 import pandas as pd import pandas io data as web aapl
  • 在谷歌云上训练神经网络时出现“无法获取路径的文件系统”错误

    我正在使用 Google Cloud 在云上训练神经网络 如下例所示 https cloud google com blog big data 2016 12 how to classify images with tensorflow u
  • Python 3在for循环中更改字典键的值不起作用

    我的 python 3 代码没有按预期工作 def addFunc x y print x y def subABC x y z print x y z def doublePower base exp print 2 base exp d
  • Pandas groupby apply 执行缓慢

    我正在开发一个涉及大量数据的程序 我正在使用 python pandas 模块来查找数据中的错误 这通常工作得非常快 然而 我当前编写的这段代码似乎比应有的速度慢得多 我正在寻找一种方法来加快速度 为了让你们正确测试它 我上传了一段相当大的
  • Pandas:将 pytz.FixedOffset 应用于系列

    我有一个带有timestamp列看起来像这样 0 2020 01 26 05 00 00 08 00 1 2020 01 26 06 00 00 08 00 Name timestamp dtype datetime64 ns pytz F
  • 根据第三个变量更改散点图中的标记样式

    我正在处理多列字典 我想绘制两列 然后根据第三列和第四列更改标记的颜色和样式 我很难改变 pylab 散点图中的标记样式 我的方法适用于颜色 不幸的是不适用于标记样式 x 1 2 3 4 5 6 y 1 3 4 5 6 7 m k l l
  • 根据列索引重命名 Dataframe 列

    是否有内置函数可以按索引重命名 pandas 数据框 我以为我知道列标题的名称 但事实证明第二列中有一些十六进制字符 根据我接收数据的方式 我将来可能会在第 2 列中遇到这个问题 因此我无法将这些特定的十六进制字符硬编码到 datafram
  • 在 matplotlib 中绘制多边形的并集[重复]

    这个问题在这里已经有答案了 我正在尝试绘制几个多边形的并集matplotlib 具有一定的 alpha 水平 我当前的代码在交叉点处颜色较深 有没有办法让交叉路口与其他地方的颜色相同 import matplotlib pyplot as
  • Python 导入非常慢 - Anaconda python 2.7

    我的 python import 语句变得非常慢 我使用 Anaconda 包在本地运行 python 2 7 导入模块后 我编写的代码运行得非常快 似乎只是导入需要很长时间 例如 我使用以下代码运行了一个 tester py 文件 imp
  • 在 HDF5 (PyTables) 中存储 numpy 稀疏矩阵

    我在使用 PyTables 存储 numpy csr matrix 时遇到问题 我收到此错误 TypeError objects of type csr matrix are not supported in this context so
  • 如何更改matplotlib中双头注释的头大小?

    Below figure shows the plot of which arrow head is very small 我尝试了下面的代码 但它不起作用 它说 引发 AttributeError 未知属性 s k 属性错误 未知属性头宽
  • 在python中对列表列表执行行总和和列总和

    我想用python计算矩阵的行和和列和 但是 由于信息安全要求 我无法使用任何外部库 因此 为了创建矩阵 我使用了列表列表 如下所示 matrix 0 for x in range 5 for y in range 5 for pos in
  • Python 中的字符串slugification

    我正在寻找 slugify 字符串的最佳方法 蛞蝓 是什么 https stackoverflow com questions 427102 in django what is a slug 我当前的解决方案基于这个食谱 http code

随机推荐

  • 计算机网络思维导图

    计算机网络思维导图 按照计算机网络的TCP IP四层模型构建 物理层对应网络接口层的功能 这个是之前期末考试时做的思维导图 现在复习专业课发现里面还有很多缺漏 希望大家多多提意见 后期有时间我也会查漏补缺的 谢谢支持 目录 计算机网络思维导
  • 集成运算放大电路实验报告_模电总结:第三章、集成运算放大电路

    我的公众号 每日晴天 可关注领取我的笔记pdf版哦 部分英文 d差模 different 差模的d c 共模 common mode 3 1多级放大电路 1 多级放大电路的组成 输入级 输入电阻高 噪声和漂移小 中间级 具有足够大的放大能力
  • android httpClient 支持HTTPS的2种处理方式

    项目中Android https或http请求地址重定向为HTTPS的地址 相信很多人都遇到了这个异常 无终端认证 javax net ssl SSLPeerUnverifiedException No peer certificate 1
  • YoloV4训练自己的数据集

    YoloV4训练自己的数据集 1 建立工作文件夹 2 准备训练数据集 3 修改配置文件 4 Anchor Box先验框聚类分析与修改 5 训练自己的数据集 6 测试训练出来的网络模型 7 性能统计 1 建立工作文件夹 新建一个项目文件夹 用
  • STM32/AMP32F407进入低功耗待机模式后立马被唤醒的解决办法

    最近项目用到低功耗 但是调试发现进入待机就被唤醒的问题 清除WU SB两个唤醒标志位 也依然被立马唤醒一次 进入待机模式 HAL PWR EnterSTANDBYMode 通过极海的数据手册终于发现 我们在使能WAKE UP PA 0唤醒脚
  • 【Linux】进程描述符

    linux进程管理 1 进程描述符 进程描述符 Linux使用进程描述符数据结构记录现场信息 然后给予进程描述符管理进程 包括进程的创建 调度 消亡等操作 进程除了包括运行着的程序 还包括系统资源 当前CPU现场 调度信息 进程间关系等 记
  • One PUNCH Man——激活函数和梯度消失/爆炸

    文章目录 什么是激活函数 激活函数介绍 梯度消失 爆炸 首先推荐一个写公式的网站 https private codecogs com latex eqneditor php 什么是激活函数 如下图 在神经元中 输入的 inputs 通过加
  • FlatBuffers在Java中的使用

    1 去maven仓库下载官网库flatbuffers java 1 7 0 1 jar 地址 点击打开链接 2 编写fbs文件 chat fbs namespace Proto 聊天频道 enum ChatChannel byte SYST
  • 利用Logstash plugins做更多的事情

    1 引言 之前一篇文章 Logstash 介绍及linux下部署 我们实现了logstash的安装以及简单的控制台标准输入输出测试 那么logstash能不能做更多的事情呢 答案是肯定的 logstash就是为了处理日志数据而生的 一个最直
  • mysql下出现Unknown column 'xx' in 'on clause'的完全解决方法

    mysql下出现Unknown column xx in on clause 的完全解决方法 在项目中执行查询无结果 在数据库运行sql报错 Unknown column xx in on clause 百度过后找到这个文章并完全解决了问题
  • 欠拟合和过拟合

    过拟合 定义 具体表现就是最终模型在训练集上效果好 在测试集上效果差 模型泛化能力弱 具体表现就是最终模型在训练集上效果好 在测试集上效果差 模型过于复杂 过拟合的原因 训练数据中噪音干扰过大 使得学习器认为部分噪音是特征从而扰乱学习规则
  • Nginx二级项目配置

    Nginx二级项目服务页面部署 应用场景 比如一个项目需要一个正常的生产服务的地址在根目录 现在需要一个后台管理项目可以部署在 admin 的路径下 需要帮助文档的页面可以部署在 help nginx conf 配置 location ma
  • 【SQL注入-08】二次注入案例—以sqli-labs-less24为例

    目录 1 二次注入概述 1 1 定义 1 2 思路 2 二次注入案例 2 1 实验平台 2 2 实验目标 2 3 具体注入过程 2 3 1 注入前准备 2 3 2 确定目标账户admin 2 3 3 第一次注入 2 3 4 第二次注入 2
  • eos bp节点 超级节点搭建

    https github com nebulaprotocol 这个网址里面有一个 fake terminal website 比较有意思 可以看看示例 https bp nebulaprotocol com 搭建eos BP节点 环境搭建
  • 家政服务小程序制作攻略揭秘

    想要打造一个家政服务小程序 但是又不懂编程和设计 不用担心 下面将为你详细介绍如何利用第三方平台 从零开始打造一个家政服务小程序 首先 你需要找到一个适合的第三方平台 例如乔拓云网 在乔拓云网的 轻应用小程序 中 点击 去管理 你就可以进入
  • 回顾2021,展望2022

    2021 这一年最大的收获是孕育了一个聪明漂亮机灵的小家伙 这一年我虚岁28岁 和爱的人有了爱的结晶 东哥各方面都挺好的 我们都不是圣人 都是能力有限的普通人 但他在尽其所能的对我好 我不是万能的人 但也独立坚强 之后一个人带娃的日子适应的
  • LaTeX公式中指定某些字母或符号为正体

    m rm G 显示效果为
  • I/O 函数/缓存和字节流、占位符、getchar(),putchar()

    I O 函数 C 语言提供了一些函数 用于与外部设备通信 称为输入输出函数 简称 I O 函数 输入 import 指的是获取外部数据 输出 export 指的是向外部传递数据 缓存和字节流 严格地说 输入输出函数并不是直接与外部设备通信
  • 从零开始学C++之异常(三):异常与继承、异常与指针、异常规格说明

    一 异常与继承 如果异常类型为C 的类 并且该类有其基类 则应该将派生类的错误处理程序放在前面 基类的错误处理程序放在后面 include
  • python3.5源码分析-启动与虚拟机

    Python3源码分析 本文环境python3 5 2 参考书籍 lt