Python源码笔记——Python中的列表对象

1.列表结构体 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #define PyObject_VAR_HEAD PyVarObject ob_base; typedef struct { PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ } PyVarObject; typedef struct { PyObject_VAR_HEAD /* Vector of pointers to list elements. list[0] is ob_item[0], etc. */ PyObject **ob_item; /* ob_item contains space for 'allocated' elements. The number * currently in use is ob_size. * Invariants: * 0 <= ob_size <= allocated * len(list) == ob_size * ob_item == NULL implies ob_size == allocated == 0 * list.sort() temporarily sets allocated to -1 to detect mutations. * * Items must normally not be NULL, except during construction when * the list is not yet visible outside the function that builds it. */ Py_ssize_t allocated; } PyListObject; ob_item是指向列表元素的指针向量,当我们通过list[0]获取元素时,实际上是获取的ob_item[0]的元素。ob_item的类型是PyObject*,由此我们可以知道,为什么Python中的list能存储任意对象的数据,这是因为任何Python对象都可以强转为PyObject*的指针类型。 ...

2023-04-07 · 6 分钟

Python源码笔记——Python中的字符串对象

1.字符串对象 在Python3.11.2中,字符串类型PyUnicodeObject的实现相当的复杂 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 typedef struct { PyObject_HEAD Py_ssize_t length; /* Number of code points in the string */ Py_hash_t hash; /* Hash value; -1 if not set */ struct { ... } state; wchar_t *wstr; /* wchar_t representation (null-terminated) */ } PyASCIIObject; typedef struct { PyASCIIObject _base; Py_ssize_t utf8_length; /* Number of bytes in utf8, excluding the * terminating \0. */ char *utf8; /* UTF-8 representation (null-terminated) */ Py_ssize_t wstr_length; /* Number of code points in wstr, possible * surrogates count as two code points. */ } PyCompactUnicodeObject; typedef struct { PyCompactUnicodeObject _base; union { void *any; Py_UCS1 *latin1; Py_UCS2 *ucs2; Py_UCS4 *ucs4; } data; /* Canonical, smallest-form Unicode buffer */ } PyUnicodeObject; 类型对象 ...

2023-04-07 · 4 分钟

Python源码笔记——Python中的整数对象

1.整数对象 在Python3.11.2中,整数结构体叫做PyLongObject。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #if PYLONG_BITS_IN_DIGIT == 30 typedef uint32_t digit; ... #elif PYLONG_BITS_IN_DIGIT == 15 typedef unsigned short digit; ... #else #error "PYLONG_BITS_IN_DIGIT should be 15 or 30" #endif typedef struct _longobject { /* PyObject ob_base; Py_ssize_t ob_size; */ PyObject_VAR_HEAD digit ob_digit[1]; } PyLongObject; 通过PyObject_VAR_HEAD我们可以确定,在新版Python中,整形是一个不定长对象。 通过前面的文章,我们知道,对于Python中的对象,与对象相关的元信息实际上都保存在与对象对应的类型对象中,对于PyLongObject,这个类型对象是PyLong_Type。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 PyTypeObject PyLong_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "int", /* tp_name */ offsetof(PyLongObject, ob_digit), /* tp_basicsize */ sizeof(digit), /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ long_to_decimal_string, /* tp_repr */ &long_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)long_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LONG_SUBCLASS | _Py_TPFLAGS_MATCH_SELF, /* tp_flags */ long_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ long_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ long_methods, /* tp_methods */ 0, /* tp_members */ long_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ long_new, /* tp_new */ PyObject_Free, /* tp_free */ }; PyLongObject对象的各种操作(比较、运算等)实际上就是调用PyLong_Type中的tp_as_number这个结构体中定义的各种函数指针。 ...

2023-04-07 · 5 分钟

Python源码笔记——Python对象机制的基石【PyObject】

所有源码均基于Python 3.11.2 1.PyObject定义 1 2 3 4 5 6 7 8 // 实际上没有任何东西被声明为PyObject,但是每个指向Python对象的指针都可以转换为PyObject*。 // 这是手动模拟的继承。同样的,每个指向可变大小的Python对象的指针也可以转换为PyObject*,此外,也可以转换为PyVarObject*。 typedef struct _object { _PyObject_HEAD_EXTRA // 定义指针以支持所有活动堆对象的双向链表refchain Py_ssize_t ob_refcnt; PyTypeObject *ob_type; } PyObject; Python通过ob_refcnt字段实现基于引用计数的垃圾回收机制。对于某一个对象A,当有一个新的PyObject*引用A对象时,A的引用计数会增加1,当这个PyObject*引用被删除时,A的引用计数应当减1,当此字段为0时,进行垃圾回收(不一定会释放内存空间,Python中还有缓存机制)。 _PyObject_HEAD_EXTRA是一个宏,当编译Python时指定参数--with-trace-refs,那么Py_TRACE_REFS 会被定义。 1 2 3 4 5 6 7 8 9 10 11 12 #ifdef Py_TRACE_REFS /* Define pointers to support a doubly-linked list of all live heap objects. */ #define _PyObject_HEAD_EXTRA \ PyObject *_ob_next; \ PyObject *_ob_prev; #define _PyObject_EXTRA_INIT _Py_NULL, _Py_NULL, #else # define _PyObject_HEAD_EXTRA # define _PyObject_EXTRA_INIT #endif ob_type是一个结构体,对应着Python内部的一种特殊的对象,用来指定一个对象类型的类型对象。 ...

2023-04-07 · 2 分钟

Mosh连接服务器时终端颜色显示问题

在使用mosh连接到服务器Ubuntu 20.04时,发现终端(终端是Kitty,支持256color)的颜色不能正常显示。 使用命令查看了一下$TERM的设置 1 2 $ echo $TERM xterm-256color 显示的是xterm-256color,说明配置的是没问题的。 查看mosh的版本: 1 2 $ mosh --version 1.3.2 可以看到mosh的版本是1.3.2,这个版本的发布日期是2017-07-22,但是github上master分支一直在开发中。 想着时间已经过去这么久了,官方应该已经解决了这个问题,毕竟现在的很多终端都是支持256color的,所以就在issue中搜索了一下,真的找到了一个解决方案。 定位问题 在2017年11月23号就有人提过关于mosh的256color显示支持问题,而官方也已经解决了这个问题,但是不知道为什么都已经过去这么久了还没有发布新的版本。 具体的issue。不过评论中说的PPA也已经很久没有更新了。所以我们需要新的方案解决Linux系统的问题。 解决方案 想要让mosh能正确的显示256color,就只能手动编译mosh的master分支。 可以查看官方的安装教程,包含手动编译的教程。 记得先将之前的安装卸载掉。 Mac 在MacOS平台上,可以使用brew来进行自动的编译和安装。 1 2 $ brew uninstall mosh $ brew install --HEAD mosh Mac在编译安装的时候,会提示更新或者安装xcode命令行工具,就按照brew执行过程中的提示操作即可。 Linux 在Ubuntu 20.04上安装,需要手动克隆mosh的仓库 在安装之前中,需要安装依赖,Ubuntu最新版本的依赖,比较少。如果你是比较旧的版本,可以参考官方的编译教程,里面有详细的依赖。 1 $ sudo apt install libncurses5-dev protobuf-compiler 1 2 3 4 5 6 $ git clone https://github.com/mobile-shell/mosh.git $ cd mosh $ ./autogen.sh $ ./configure $ make $ sudo make install 最后执行make install的时候,最好添加sudo,因为涉及到将编译生成的可执行文件复制到系统可查找到的bin目录下。 ...

2019-06-01 · 1 分钟

关于Go Modules的一些内容

启用Go Modules go mod在Go >= 1.13才默认启用,在Go >= 1.11已经开始支持了go mod。 设置环境变量 1 2 3 4 5 6 7 8 9 # 启用go module export GO111MODULE=on # 设置GOPATH,开启go mod之后,这个目录主要用来存放依赖包 export GOPATH=~/go_modules # 设置go代理,在运行go test/build等时会自动下载依赖 # 使用go get下载依赖需要在GOPATH中执行才会使用代理 export GOPROXY=https://goproxy.io go mod使用 在$GOPATH/src之外的任意目录创建一个目录, 1 2 mkdir -p /home/gopher/project cd /home/gopher/project 这个目录就是你项目的根目录,在目录中创建mod管理文件 1 go mod init project 如果你这个项目是放在github上的,那么在创建文件的时候可以这样写,project为你github项目名称 1 go mod init github.com/YourName/project go.mod的初始内容cat go.mod为: 1 2 3 module project go 1.12 go.mod只需要在项目的根目录创建一次即可,在项目中Go会自动查找当前目录的全部父级目录,直到找到go.mod。 ...

2019-06-01 · 1 分钟

Jenkins处理GitLab Hook

jenkins安装Generic Webhook Trigger Plugin插件 {% asset_img Generic_Webhook_Trgger.png Generic\ Webhook\ Trgger具体配置 %} 创建任务,在构建触发器中勾选Generic Webhook Trigger, 在展开的页面中会有一个URL, 这个URL是配置Webhook使用的,一般形式是http://JENKINS_URL/generic-webhook-trigger/invoke, JENKINS_URL是初始配置jenkins时会有的,一般是http://IP:8080的形式。 如果之前有配置过GitLab webhook, 请去除这个,不然Generic Webhook Trigger不会生效。 如果Git仓库的验证使用的是用户名和密码,那么就不需要配置Token. 复制这个URL,将JENKINS_URL替换为自己的真实数据,在GitLab的对应的项目的设置-->集成中输入,没有安全令牌,勾选自己需要的触发器事件,SSL证书验证可以开启,也可以不开启,推荐开启。 任务设置界面还有Post content parameters, Header parameters, Request parameters, 分别是请求的post数据,header头,请求头。 一般我们只需要post的数据里的内容就够了。 图片的3,4分别是变量名(3),值(4)。值是直接从post的json格式的数据中取出来的,注意,值的获取方式是JSONPath,并且里面有点,如果json数据有多层,那么就多点几次,比如$.project.name等,可以配置多个变量组。 我们还可以Generic Webhook Trigger配置Optional filter,设置一个触发事件,比如只有当你推送的分支是develop的时候,才去构建。 在Optional filter的Expression框中输入^(refs/heads/develop)$, 在下面的Text框中输入步骤3的变量名,这里写$ref。 在shell中使用变量名的方式也是直接使用,例如echo $ref, 注意没有点。 配置完成后,保存,可以点击刚刚配置的GitLab的webhook页面的Test对应的事件测试。 GitLab的push的hook数据: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 { "object_kind": "push", "before": "95790bf891e76fee5e1747ab589903a6a1f80f22", "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "ref": "refs/heads/master", "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "user_id": 4, "user_name": "John Smith", "user_username": "jsmith", "user_email": "john@example.com", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 15, "project":{ "id": 15, "name":"Diaspora", "description":"", "web_url":"http://example.com/mike/diaspora", "avatar_url":null, "git_ssh_url":"git@example.com:mike/diaspora.git", "git_http_url":"http://example.com/mike/diaspora.git", "namespace":"Mike", "visibility_level":0, "path_with_namespace":"mike/diaspora", "default_branch":"master", "homepage":"http://example.com/mike/diaspora", "url":"git@example.com:mike/diaspora.git", "ssh_url":"git@example.com:mike/diaspora.git", "http_url":"http://example.com/mike/diaspora.git" }, "repository":{ "name": "Diaspora", "url": "git@example.com:mike/diaspora.git", "description": "", "homepage": "http://example.com/mike/diaspora", "git_http_url":"http://example.com/mike/diaspora.git", "git_ssh_url":"git@example.com:mike/diaspora.git", "visibility_level":0 }, "commits": [ { "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", "message": "Update Catalan translation to e38cb41.", "timestamp": "2011-12-12T14:27:31+02:00", "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", "author": { "name": "Jordi Mallach", "email": "jordi@softcatala.org" }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] }, { "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "message": "fixed readme", "timestamp": "2012-01-03T23:36:29+02:00", "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "author": { "name": "GitLab dev user", "email": "gitlabdev@dv6700.(none)" }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] } ], "total_commits_count": 4 }

2019-06-01 · 2 分钟

Jenkins与RocketChat集成

Jenkins与RocketChat集成 在Jenkins中安装插件RocketChat Notifier 配置信息 点击Jenkins左侧的系统管理-->系统设置, 找到Global RocketChat Notifier Settings. 配置Rocket Server URL, 是URL:PORT的类型, 例: http://chat.xxxx.com:80. 配置Login Username和Login password, 是RocketChat的账号密码. Channel, 发送的频道. Build Server URL, 构建的服务器和端口, http://192.168.0.1:8080 点击Test Connection, Success表示配置成功.

2019-06-01 · 1 分钟

Jenkins+Python+GitLab持续集成

创建任务 登录Jenkins,点击左侧列表的新建选项。输入任务名称,选择构建一个自由风格的软件项目,点击确定。 配置 在任务配置界面,可以设置General标签中的丢弃旧的构建选项,设置保持构建的天数和保持构建的最大个数。 点击源码管理标签,选择git,在Repository URL中输入Git仓库的链接。 如果是HTTP链接,选择Credentials一行的Add > Jenkins,在Kind一行下拉选择Username with password,在下方Username和Password框中输入用户名和密码。 使用docker jenkins容器里面的ssh-key。 直接使用服务器的ssh key就可以了。如果指定Path to key需要使用docker中的ssh key。如果使用Source files那么需要使用docker容器中的key, 因为Source files的相对路径不是固化到本地的路径, 而是docker中的路径. 如果是SSH链接,选择SSH Username with private key,在Username框中输入用户名,Private Key 选择为Enter directly,在显示的key框中输入私钥。(生成秘钥ssh-keygen -t rsa -C "email.com",生成的文件在home目录下的.ssh目录下,使用命令cat id_rsa查看私钥,复制到key框中)。点击最下方的Add按钮,保存设置。 在Credentials的下拉选项中选择刚刚创建Username。 使用定时任务 在构建触发器标签里选择Poll SCM,输入H/2 * * * *, 最后点击保存。 这是一个定时任务,每隔2分钟查询一次代码,如果有更新,就执行任务。 使用webhook 使用webhook比定时任务更好,webhook只有在push或指定操作时,jenkins会拉取代码,不用定时访问,耗费资源。 需要安装的插件Gitlab Hook、GitLab、Gitlab Authentication、Build Authorization Token Root 配置job,在构建触发器中勾选Build when a change is pushed to GitLab. GitLab CI Service URL: http://服务器IP:8080/project/demo ,URL后面是回调地址,再点击高级,再Secret token行,点击Generate生成token。 在GitLab服务器上的相对应的项目的Settings里面的Integrations中,配置webhook,输入在jenkins中获取的URL,和token,可以根据需要勾选事件,开启SSL,点击Add webhook。会在Add webhook按钮下生成一个webhook,点击test,会弹出勾选的事件,选择相应的事件,会在页顶弹出Hook executed successfully: HTTP 200,到此,webhook配置完成。 ...

2019-06-01 · 2 分钟

Jenkins+Git子模块自动拉取代码

jenkins+Git子模块自动拉取代码 添加Git子模块 先克隆想要添加子模块的仓库git clone ssh://git@ip:port/user/project.git,这个是主目录。 进入仓库,添加子模块git submodule add ssh://git@ip:port/user/project.git,和主仓库不同。 ls查看,会有.gitmodules和子模块的项目名。 将生成的文件和目录push到主仓库中。 克隆有子模块的仓库 添加过子模块的仓库,如果想重新克隆,和普通克隆一样,不过克隆后需要在仓库目录下执行 git submodule init和git submodule update,如果不执行,子模块中会没有文件。 更改子模块的分支 切换到子模块目录,默认子模块是master分支,git submodule foreach git checkout dev, 然后使用git submodule foreach git pull切换分支。 需要在jenkins任务的构建步骤中添加git submodule init和git submodule update,以及上述操作(写在这两个命令后面), jenkins才能拉取到代码。 submodule可以进行tag和merge git submodule foreach可以分别对子模块进行操作, 所以对所有子模块进行tag和merge操作, 就相当于对总项目进行相应的操作.

2019-06-01 · 1 分钟