|
|
Hexo是一个比较火的博客框架(主观),然后我使用了其中的Tranquilpeak主题,但是发现写着写着发现,本来应该等宽的代码部分明显不是等宽的,然后就翻文档
Change global style
If you want to change font families, font size, sidebar color, things like that, take a look at
source/_css/utils/_variables.scss
file. This file contains global variables used in this theme. Build the theme after changes to see changes.
OK,接着翻源码
|
|
Menlo这个字体是mono space的呀,怎么显示不对呢,然后我注意到这么一段话:
Menlo是一个无衬线等宽字体,由Jim Lyles设计,首次出现于2009年8月上市的Mac OS X Snow Leopard系统内建字体之一。基于开源字体Bitstream Vera与自由版权字体DejaVu字体改良而来
什么?Mac OS X内建字体?那也就是说本穷用的Windows 10 Home应该是不会有咯。然后本穷就下载,安装,重启浏览器,OK,终于显示正确了。
总结
Web开发不得不考虑跨平台的问题,所以一定不能在字体这个地方栽跟头,不能说你用的Mac开发的你就用Menlo不管了,好歹加个备选的monospace。
issue给作者之后发现,问题已经被fix,但是还得等下个版本release才能见到。这又教导我,在issue之前最好好好搜一下已有的issue和pull request,已经有的问题不要重复开issue。
介绍
本文提供Python的C实现的C代码的编码风格。Python代码的风格指南参见相关信息的PEP[1]。
注意,规则有时也会被打破。两个打破特定规则的好的理由:
- 当遵循这个规则回事代码更少地可读,即使其他人依据此规则去阅读代码。
- 未保持和周围也打破规则的代码一致(也许是历史原因)–尽管有一个机会去清理别人的烂摊子(以真正的XP格式)
C方言
- Python 3.6之前使用的是ANSI/ISO标准C(1989版标准)。这意味着(以及其他许多情况)所有的申明都必须在代码块顶部(不需要再函数的顶部)。
- Python 3.6及之后的版本使用采用了部分C99特性的C89:
- 标准整形在
<stdint.h>
和<inttypes.h>
中。我们要求定宽的整形类型。 static inline
函数- 指定初始化器(designated initializers),对类型定义特别好。
- 混合申明
- 布尔值
- C++风格的行注释
未来C99的特性可能会被添加到这个列表视编译器支持而定(主要是MSVC)。
- 标准整形在
- 不要使用GCC拓展(例如,不要写没有行尾的反斜杠的多行字符串)
- 所有的函数申明和定义必须使用完全原型(例如,指定所有参数的类型)
- 永远不要使用C++风格的
//
一行注释 - 在几种主要编译器(gcc,VC++,一些其他的)上没有警告
代码布局
- 使用4个空格缩进并完全禁用tab。
- 每行不得超过79个字符。如果这一条和前一条一起没有给你的代码足够的空间,那么你的代码就太复杂了–考虑使用子程序。
- 函数定义格式:函数名在第1列,最外面的花括号在第一列,在本地变量申明之后留空行。
|
|
- 代码结构:在诸如
if
,for
等关键词和接下来的左括号直接一个空格;在括号内没有空格;大括号被强烈推荐使用但可在C允许的情况下省略,并且它们应格式化成下面所示:
|
|
return语句不应有多余的括号:
return Py_None; /* correct */
return(Py_None); /* incorrect */
函数和宏的调用风格:
foo(a, b, c)
–在左括号之前没有空格,在括号中没有空格,在逗号前没有空格,在每个逗号后一个空格。总是在赋值符号,布尔值和比较符两边加上括号,在表达式中使用了很多操作符,在最外面的(最低优先级)的两边加上空格。
长行换行:如果可以,在最外层表达式的逗号后折行。总是保持缩进
123PyErr_Format(PyExc_TypeError,"cannot create '%.100s' instances",type->tp_name);当你在长表达式的二元操作符处换行,这个操作符跟在前一行的行末,例如:
1234if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 &&type->tp_dictoffset == b_size &&(size_t)t_size == b_size + sizeof(PyObject *))return 0; /* "Forgive" adding a __dict__ only */在函数、结构定义、函数的主要片段的前后留空行。
注释放在它们描述的函数之前。
所有的函数和全局变量申明为static,除非他们是发布的接口的一部分
对于外部函数和变量,我们总是在“Include”文件夹中合适的头文件中声明,使用PyAPI_FUNC()宏,如:
PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *);
命名习惯
公共函数使用
Py
前缀;永远不要给静态函数(使用Py
前缀)。Py_
前缀给全局服务例程如Py_FatalError
;特定的服务组(例如特定对象类型API)使用长前缀例如字符串使用PyString_。公共函数和变量使用混合大小写以及下划线,例如这些:
PyObject_GetAttr
,Py_BuildValue
,PyExc_TypeError
。偶尔的一个“内部”函数需要对加载器可见,对此我们使用
_Py
前缀,例如:_PyObject_Dump
。宏应该是混合大小写的前缀跟着大写,例如:
PyString_AS_STRING
,Py_PRINT_RAW
。
文档字符串
对文档字符串使用
PyDoc_STR()
或者PyDoc_STRVAR()
宏以获得无文档字符串地编译Python(./configure --without-doc-strings
)。对于需要支持早于2.3版本Python的C代码,你可以在引入
Python.h
后包含如下:12345函数文档字符串的第一行应是一个“签名行”–给出一个参数和返回值简短的概要,例如:
123PyDoc_STRVAR(myfunction__doc__,"myfunction(name, value) -> bool\n\n\Determine whether name and value make a valid pair.");总是包含一个空行在签名行和描述的文本之间。
如果函数的返回值总是为
None
(因为没有有意义的返回值),不要写返回类型的提示。当写多行文档字符串时,确保总是像上面例子中使用反斜杠继续,或者字符串字面相连:
123PyDoc_STRVAR(myfunction__doc__,"myfunction(name, value) -> bool\n\n""Determine whether name and value make a valid pair.");尽管一些C编译器接受没有上述两种规范的字符串:
1234/* BAD -- don't do this! */PyDoc_STRVAR(myfunction__doc__,"myfunction(name, value) -> bool\n\nDetermine whether name and value make a valid pair.");不要这么做;已知MSVC编译器会抱怨这个。
参考
[1] | PEP 8 , “Style Guide for Python Code”, van Rossum, Warsaw ( http://www.python.org/dev/peps/pep-0008 ) |
版权信息
此文档已放在公共领域。
0. 前言
年初的时候给自己挖了一个坑,计划要在今年过一遍Python的源码。结果这一年零零碎碎总有事情耽搁了。现在已经10月份了,再不填坑就来不及了。于是有了这个系列。
说到看Python源码,陈儒的Python源码剖析可谓经典了。本系列基本也是根据此书的结构的。不过此书出版已近十年(2016-10),Python版本也从2.5到了3.5。不才能力有限,姑妄言之。
运行环境:Bash on Ubuntu on Windows,同样适用其他于UNIX-like环境。
1. 获取Python源码
你可以选择2.7.12或 3.5.2。当然你也可以使用hg clone https://hg.python.org/cpython
和hg update 3.5
这样的命令来选择你喜欢的版本分支。(hg通过sudo apt install mercurial安装)
值得注意的是,CPython会检测到是否是从工作拷贝(由hg clone的)运行。这意味着如果你在你的拷贝中编辑CPython源码,Python代码(.py文件)的改变会被解释器立即使用和测试。(如果你修改的是C代码,你将需要重新编译受影响的文件)。
2. 编译为调试模式
CPython提供几种编译flag帮助调试很多东西。所有已知的flag都可以在Misc/SpecialBuilds.txt
文件中找到,最常用的是Py_DEBUG
标志。
构建debug版的Python,可以在源码根目录中运行./configure --with-debug
2.1. 构建依赖
CPython的核心解释器需要C编译器构建。一些拓展模块也依赖额外的库。
Debian/Ubuntu系的可执行如下命令安装依赖:
sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils
Mac OS X:
brew install readline xz
其他发行版本参见参考资料[2]。
3. 目录结构
大部分的子文件夹都有自己的README。大部分的文件都有注释。
文件或文件夹 | 简介 |
---|---|
Demo/ | 示例脚本,模块和程序 |
Doc/ | 文档源(reStructuredText) |
Grammar/ | Python的EBNF语法文件 |
Include/ | 公共头文件 |
LICENSE | 授权信息 |
Lib/ | Python部分标准库,均是Python写的 |
Mac/ | Macintosh特定的资源(例如,用IDLE作为OS X的应用) |
Makefile.pre.in | Source from which config.status creates the Makefile.pre |
Misc/ | 其他有用的文件 |
Modules/ | 大部分内置模块的实现 |
Objects/ | 大部分内置对象类型的实现 |
PC/ | PC特定的文件(DOS, Windows, OS/2) |
PCbuild/ | Microsoft Visual C++的build目录 |
Parser/ | 解析器和分词器以及他们的输入处理AST的节点也在这个文件夹 |
Python/ | 字节编译器和解释器,Python核心部分。 |
README | 读我 |
RISCOS/ | RISC操作系统特定的文件 |
Tools/ | 一些用Python写的有用的程序 |
pyconfig.h.in | Source from which pyconfig.h is created (GNU autoheader output) |
configure | 配置的shell脚本(GNU autoconf的输出) |
configure.ac | 配置格式(GNU autoconf的输入) |
install-sh | 用来安装文件的Shell脚本 |
4. 贴士
4.1. Py_ssize_t
首先理解什么是size_t,然后是ssize_t,然后你就知道什么是Py_ssize_t了。
4.2. int_repr
在最新的Python代码中没有了int_repr这个函数,甚至没有了intobject。善用搜索引擎,发现了旧版本的intobject.c中有两处int_repr,一处是定义,一处是引用。(reprfunc)int_repr, /* tp_repr */
拿注释tp_repr
在新版里搜,发现了long_to_decimal_string, /* tp_repr */
不出意外这就是改动后的函数,试试再按Python源码剖析的例子操作,成功输出。
参考资料:
[1] Python Developer’s Guide — Python Developer’s Guide
[2] Common build problems · yyuu/pyenv Wiki
欢迎来到我的博客!
头像是我的男神薛定谔。