Welcome to use python documentation!¶
Contents:
python包管理¶
Page Status: | Development |
---|---|
Last Reviewed: |
python的一大优点是第三方库的丰富易用
我们将在 打包并发布 一章中介绍python库的结构,在这边我们先介绍如果获取和管理第三方库
手工下载安装库¶
直接下载并解压库的zip或者tar.gz包,运行命令 python setup.py install
注解
如果提示找不到setuptools,需要先安装setuptools库
注解
这种安装方法不会自动安装库的依赖
使用easy_install管理第三方库¶
安装 setuptools¶
可以直接下载压缩包,解压安装。或者对于联网的机器,也可以使用 ez_setup.py 安装:
python ez_setup.py
安装 setuptools 结束之后, easy_install也会被同时安装。 将easy_install的路径加入执行路径后,在console中就可以使用easy_install来安装python包,easy_install支持离线安装(zip包,tar包,exe包)和在线安装(PyPI URL),并且能自动下载安装依赖包:
easy_install [options] package_pat/URL
注解
对于使用代理的机器,在使用easy_install之前需要先设置console的环境变量来指明代理
set http_proxy=...
set https_proxy=...
使用pip管理第三方库(推荐)¶
安装pip¶
pip已经在python 3.4中默认包含,如果使用的是其他的python版本,需要先安装pip,三种方法:
- 下载 pip安装包 安装
easy_install pip
- 下载 get-pip.py , 执行命令
python get-pip.py
使用pip¶
pip的用法和easy_install类似,但支持更多的功能:
Usage:
pip <command> [options]
Commands:
install Install packages.
uninstall Uninstall packages.
freeze Output installed packages in requirements format.
list List installed packages.
show Show information about installed packages.
search Search PyPI for packages.
wheel Build wheels from your requirements.
zip DEPRECATED. Zip individual packages.
unzip DEPRECATED. Unzip individual packages.
help Show help for commands.
General Options:
-h, --help Show help.
--isolated Run pip in an isolated mode, ignoring
environment variables and user configuration.
-v, --verbose Give more output. Option is additive, and can be
used up to 3 times.
-V, --version Show version and exit.
-q, --quiet Give less output.
--log <path> Path to a verbose appending log.
--proxy <proxy> Specify a proxy in the form
[user:passwd@]proxy.server:port.
--retries <retries> Maximum number of retries each connection should
attempt (default 5 times).
--timeout <sec> Set the socket timeout (default 15 seconds).
--exists-action <action> Default action when a path already exists:
(s)witch, (i)gnore, (w)ipe, (b)ackup.
--trusted-host <hostname> Mark this host as trusted, even though it does
not have valid or any HTTPS.
--cert <path> Path to alternate CA bundle.
--client-cert <path> Path to SSL client certificate, a single file
containing the private key and the certificate
in PEM format.
--cache-dir <dir> Store the cache data in <dir>.
--no-cache-dir Disable the cache.
--disable-pip-version-check
Don't periodically check PyPI to determine
whether a new version of pip is available for
download. Implied with --no-index.
注解
对于使用代理的机器,在使用pip时候需要指明代理
pip install XXX –proxy <proxy>
python编程模式¶
本章介绍python编程中常用到的一些模式,面向有一定python编程经验的程序员,来提高和完善自己的python知识。
初学者最好首先参考一本python入门读本,推荐O’REILLY出版的 learning python
everything is object¶
Python是一门动态语言,所有的类型(函数,类,实例)都是一个object,可以被赋值给任意的变量,给python编程带来非常大的灵活性。
代码示例,动态调用函数:
functions = {
"func1": func1,
"func2": func2,
}
def func1():
print(1)
def func2():
print(2)
if __name__=="__main__":
import sys
func_name = sys.argv[1]
functions[func_name]()
迭代器和组合操作¶
迭代器和组合操作是python 从Haskell借鉴的语法
迭代器¶
迭代器可以有多种实现方式:
- 实现__iter__和next方法的object, 参见 iterator-types
- 使用yield的generator, 参见 yield expressions
- 使用built-in函数iter构造的迭代器, 参见 iter statement
迭代器的使用:
- 用在for表达式中, 参见 for statement
组合操作¶
组合操作比一般的循环操作节省代码,而且能提高性能,组合操作会使用C的循环,而不是一般的python循环,python推荐使用组合操作来生成列表。
组合操作形式:
[ [expression] for object in iter_object [for_or_if_expression] ]
示例1:
>>> res = []
>>> for line in open('script1.py'):
... if line[0] == 'p':
... res.append(line.rstrip())
...
>>> res
['print(sys.path)', 'print(2 ** 33)']
>>> lines = [line.rstrip() for line in open('script1.py') if line[0] == 'p']
>>> lines
['print(sys.path)', 'print(2 ** 33)']
示例2:
>>> res = []
>>> for x in 'abc':
... for y in 'lmn':
... res.append(x + y)
...
>>> res
['al', 'am', 'an', 'bl', 'bm', 'bn', 'cl', 'cm', 'cn']
>>> [x + y for x in 'abc' for y in 'lmn']
['al', 'am', 'an', 'bl', 'bm', 'bn', 'cl', 'cm', 'cn']
动态加载模块¶
Python通过 __import__ 函数支持动态加载模块
动态加载os模块:
os_module = __import__("os")
动态加载os.path模块:
os_path_module = __import__("os.path", fromlist=["join"])
注解
如果没有fromlist参数,即使模块名字是 os.path
,也只会返回os模块:
os_module = __import__("os.path")
注解
在python 2.7和python 3之后,也可以使用 importlib.import_module() 来动态加载模块
return VS exception¶
关于使用返回值还是使用异常的建议:
- 我们应该对使用返回值的情景和使用异常的情景进行区分,使用返回值来表达函数的状态是不推荐的,会导致上层编码风格的混乱
- 只使用返回值来传递数据,如果函数没有想要返回的值,尽量不要在函数中使用return,python会默认返回None
- 使用具体的异常类型,比如built-in的
ValueError
,AttributeError
, 不要使用Exception
, 如果需要自定义异常,将自定义的异常统一放到一个模块中,这样上层代码能方便访问你的自定义异常 - 尽量统一在上层处理异常,中间层尽量不处理异常,让异常扩散到统一处理异常的地方
property VS method¶
关于使用属性还是方法的建议:
- 属性一般意味着从内存中直接拿出之前存储的值
- 方法意味着需要一定的处理
- 如果设计上想让外部以为是属性,但需要一定的内部处理,可以使用 @property 修饰
Unicode¶
这个关于unicode的章节是针对python 2的。
hex转义¶
str类型可以存储所有的ascii码的字符,比如英文字母,数字和一些标点符号。但对于其他语种里面的字符,比如中文字符,则需要特殊的存储处理。
str类型对于非ascii的字符,是直接存储该字符的二进制值(使用某种编码格式),可以用hex转义的str来存储这种二进制值。
示例代码如下,解析器的编码格式是UTF-8:
>>> a = "你好"
>>> a
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> c = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print(c)
你好
编解码(encode & decode)¶
编码将unicode转化成某种编码格式,编码将某种编码格式转化成unicode,标准编码格式见 Standard Encodings
一般国际通用的编码格式是UTF-8,中文有时候会用gb2312,gbk编码,推荐使用UTF-8的编码格式。
示例代码如下,解析器的编码格式是UTF-8:
>>> a = "你好"
>>> a
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> b = a.decode("utf-8")
>>> b
u'\u4f60\u597d'
>>> c = b.encode("utf-8")
>>> c
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> a == c
True
文本文件和解析器本身的编码¶
文本文件和解析器这种需要向用户显示信息的地方,一般都有自己的编码格式,能将二进制数据显示成文本,或将文本存储成二进制数据。
当编辑器载入文本的时候,需要知道文本的编码格式,才能正确显示。编辑器如何知道文本的编码格式呢,不同的文本格式的规则也有所不同。
- Windows文本文件会在文件开头添加一些额外的字节来标识不同的编码格式
- python脚本默认编码格式是UTF-8,可以在文本开头添加
# -*- coding: latin-1 -*-
来声明编码格式 - XML默认编码格式是UTF-8,可以在开头添加
<?xml version="1.0" encoding="ISO-8859-1"?>
来声明编码格式 - HTML默认编码格式是UTF-8,可以在开头添加
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
来声明编码格式
python解析器在不同平台上使用的编码格式也可能不同
Windows console:
>>> import locale
>>> locale.getdefaultlocale()
('en_US', 'cp1252')
Ubuntu terminal:
>>> import locale
>>> locale.getdefaultlocale()
('en_PH', 'UTF-8')
线程和全局锁(GIL)¶
GIL 使得python的解析器运行在一个单线程上,简化python的解析器的实现,提高性能。 代价是python中多线程不能把load分配给CPU的多核, 参见 Thread State and the Global Interpreter Lock
所以在python执行并行任务,可以尽量使用多进程来提高效率 multiprocessing
当然,在必须使用线程的情况下,比如UI应用,可以使用python提供的线程库 threading,但是不能利用CPU的多核来提高性能。
垃圾回收机制¶
Python有一个自动的垃圾回收机制,原理如下:
- python解析器对所有的object做引用计数,每次垃圾回收时,没有被引用的object会被free
- 当内存分配的object足够多的时候,python垃圾回收会自动运行,自动垃圾回收的频率可以通过
gc.set_threshold
设置 - python垃圾回收机制将object分成三类, threshold0~threshold2, object的threshold越高, 执行自动垃圾回收的频率越低
- python垃圾回收会释放循环引用的object
- 循环引用,且包含__del__方法的object,不会被垃圾回收释放
- 可以通过调用
gc.collect
手动运行垃圾回收
注解
频繁的垃圾回收对python应用的性能有明显影响,所以运行垃圾回收需要有一些注意:
- 不要频繁的运行垃圾回收
- 在不经常运行的代码后面加入手动垃圾回收
- 在性能要求高的代码段不要运行垃圾回收,在这些代码段运行接收再进行垃圾回收
更多参考:
面向对象设计和编程¶
python提供了 一套面向对象的语言特性,来支持面向对象设计和编程
模板和接口¶
动态绑定¶
多重继承问题¶
python class支持多重继承,但需要注意的,使用多重继承时,python查找成员的机制。
- 对于old-style的类(python 2中不继承object的类),查找成员的顺序是由左到右,深度优先
- 对于new-style的类(python 2中继承object的类,python 3中所有的类都是new-style的), 查找顺序遵循 MRO(Method Resolution Order)
修饰器¶
元类¶
匿名函数¶
在python中使用设计模式¶
单元测试¶
Page Status: | Development |
---|---|
Last Reviewed: |
参见 Python guide, Testing Your Code
注解
Python guide, Testing Your Code 推荐的几个测试框架/工具中,
个人推荐 mock工具,对其他的unit test框架是否比python built-in的 unittest
框架好,我保留意见。
python代码质量¶
Page Status: | Development |
---|---|
Last Reviewed: |
python编码风格建议¶
注解
关于使用返回值还是使用异常的建议:
- 我们应该对使用返回值的情景和使用异常的情景进行区分,使用返回值来表达函数的状态是不推荐的,会导致上层编码风格的混乱
- 只使用返回值来传递数据,如果函数没有想要返回的值,尽量不要在函数中使用return,python会默认返回None
- 使用具体的异常类型,比如built-in的
ValueError
,AttributeError
, 不要使用Exception
, 如果需要自定义异常,将自定义的异常统一放到一个模块中,这样上层代码能方便访问你的自定义异常 - 尽量统一在上层处理异常,中间层尽量不处理异常,让异常扩散到统一处理异常的地方
python编码检查工具¶
pylint¶
使用 pylint 相当简单,参见 A Beginner’s Guide to Code Standards in Python - Pylint Tutorial
注解
pylint 的默认设置有时候太严格了,我们可以通过创建pylint的configure文件来声明我们需要enable/disable哪些规则
- 首先,我们生成一份sample configure文件,
pylint --generate-rcfile sample_config
- 在文件中找到
[MESSAGES CONTROL]
段,设置enable=
disable=
为需要打开/关闭的规则,规则列表见 pylint-checkers-options-and-switches - configure文件需要放到合适的位置, 当前文件夹下的 pylintrc 文件 > 环境变量 PYLINTRC 指明的文件 > 用户目录下的 .pylintrc 文件 > /etc/pylintrc
landscape¶
一个python代码质量检查网站,对于开源工程是免费的。如果你的工程是一个host在GitHub上的开源的python工程,这个网站是一个很好的代码质量检查工具。
参考它的文档: landscape文档
打包并发布¶
Page Status: | Development |
---|---|
Last Reviewed: |
之前的一章我们介绍了如何下载和管理第三方库,这里我们介绍如何生成并发布我们自己的库
python库结构¶
一般的python库结构:
package folder -+
|
+setup.py <--主要的配置/安装文件,必须
|
+setup.cfg <--提供给用户的配置文件,可选
|
+README <--readme文件,可选
|
+MANIFEST.in <--打包配置文件模板,用来和setup.py一起生成打包配置文件MANIFEST,可选
|
+<your package> <--你的package,最好与package folder名字一致
|
+<other files> <--额外的文件
利用 distutils
打包¶
disutils
是python的标准库,提供了基本的工具集来打包和发布python库, 同时也确立了python库的基本结构。
我们可以利用 disutils
来快速的为我们自己的package构建一个标准的库,步奏如下:
1. 创建package同名文件夹
2. 将package放到文件夹中,同时新建文件setup.py
3. 编辑setup.py文件,从disutils.core中加载setup函数,并给setup函数添加参数(project信息)
4. 如果需要,添加MANIFEST.in,来处理setup.py打包时没有添加库里面的文件,见 `MANIFEST.in语法 <https://docs.python.org/3.4/distutils/sourcedist.html#specifying-the-files-to-distribute>`_
5. 运行命令python setup.py sdist生成库
setup函数的参数:
name
工程名字,名字中可以包含的字符见 `PEP426 <http://legacy.python.org/dev/peps/pep-0426/#name>`_
version
工程版本,格式见 `PEP440 <https://pypa.io/en/latest/peps/#pep440s>`_:
1.2.0.dev1 # Development release
1.2.0a1 # Alpha Release
1.2.0b1 # Beta Release
1.2.0rc1 # RC Release
1.2.0 # Final Release
1.2.0.post1 # Post Release
description
工程描述
url
工程地址
author
作者信息
license
许可证信息
classifiers
一组你的工程相关的信息,PyPI会利用这些信息来给你的工程分类,见 https://pypi.python.org/pypi?%3Aaction=list_classifiers
keywords
一组关键字来描述你的工程
packages
你的工程中包含的package,需要列出所需的所有package和subpackage,disutils不会自动寻找subpackage
install_requires
依赖列表,pip安装时候会根据这个列表来自动安装所需依赖库,比如sphinx的依赖列表::
install_requires = [
'six>=1.4',
'Jinja2>=2.3',
'Pygments>=1.2',
'docutils>=0.10',
'snowballstemmer>=1.1',
'babel',
]
package_data
package中的数据列表,生成库的时候这个列表中的数据都会被加进MANIFEST文件
安装库的时候,这个列表中的数据会被安装
data_files
和package_data的区别在于,data_files列出的数据不在package中
scripts
entry_points
console_scripts
注解
如果使用python2.6或之前的版本,即使package_data中列出了文件,在MANIFEST.in仍然需要再添加一遍
利用 setuptools
打包 (推荐)¶
setuptools
是另一款第三方的打包发布工具集,兼容 disutils
的库结构
setuptools
的使用步骤和 disutils
类似,添加优化了一些功能,使得打包发布更加容易
主要增强的功能有:
- 自动查找/下载/安装/升级库的依赖
- 自动包含所有的packages,不需要全部列出了
- 自动包含所有的相关的data文件,不需要新建一个MANIFEST.in文件了
新增或改变的setup函数的参数:
include_package_data
设成True,则自动添加你的工程目录中的所有的文件,如果没有额外的指明,只添加全部的文件
exclude_package_data
指明了需要排除的文件
package_data
指明了需要添加的文件
zip_safe
指明你的工程是否能够以压缩的格式安装
install_requires
依赖
注解
其他的关键字见 setuptools新增改变的关键字列表
注解
setuptools 通过find_packages函数来自动包含所有的packages,对于大型软件来说,极大的方便了packages的管理
find(cls, where='.', exclude=(), include=('*',))
method of __builtin__.type instance
Return a list all Python packages found within directory 'where'
'where' should be supplied as a "cross-platform" (i.e. URL-style)
path; it will be converted to the appropriate local path syntax.
'exclude' is a sequence of package names to exclude; '*' can be used
as a wildcard in the names, such that 'foo.*' will exclude all
subpackages of 'foo' (but not 'foo' itself).
'include' is a sequence of package names to include. If it's
specified, only the named packages will be included. If it's not
specified, all found packages will be included. 'include' can contain
shell style wildcard patterns just like 'exclude'.
The list of included packages is built up first and then any
explicitly excluded packages are removed from it.
注解
对于使用setuptools来打包的库,用户安装使用之前需要安装合适版本的setuptools
setuptools为本机没有安装setuptools的用户提供了一个解决方法,在安装库之前自动安装setuptools:
下载 ez_setup.py ,并包含在库根文件夹下
同时在setup.py中添加:
try:
from setuptools import setup, find_packages
except ImportError:
import ez_setup
ez_setup.use_setuptools()
from setuptools import setup, find_packages
上传库到PyPI¶
- 注册账号,建议通过 PyPI用户注册界面 完成注册
- 注册工程,进入工程目录,
python setup.py register
,最后提示保存pypi账号的时候,确认保存 - 上传工程,建议使用 twine 来上传
twine upload dist/*
注解
在使用代理的机器上,需要首先设置console的环境变量来指明代理
set http_proxy=...
set https_proxy=...
编译成二进制文件¶
Page Status: | Development |
---|---|
Last Reviewed: |
对于某些应用,可能会需要将python应用打包成独立的可执行文件,这样可以发布给别人直接使用,不需要安装python或其他依赖,而且可以某种程度上保护源代码。 一般对于desktop app有这样的需求,对于web app,脚本,python库一般没有这样的需求。
下面介绍几个python工具来满足这种需求
py2exe¶
py2exe支持将python app转化成windows exe,支持python2.7和python3.3
py2exe for python2.7 host在 sourceforge上
py2exe for python3.3 host在 PyPI上
基本使用步奏¶
- 安装py2exe
- 安装打包所需windows runtime, 对于python2.7和python3.3, 需要安装VS2008或 Microsoft Visual C++ 2008 Redistributable Package
- 编写或修改setup.py,setup.py中py2exe的参数参考 ListOfOptions
- 打包
python setup.py sdist py2exe
一个加入py2exe支持的setup.py,和普通的setup.py的比较:
注解
如果安装完windows runtime,仍然提示 msvcp90.dll
找不到,你需要手动将 msvcm90.dll, msvcp90.dll, msvcr90.dll
拷贝到 C:\Python27\DLLs\
如果安装了VS2008,这些文件路径位于 C:\\Program Files\\Microsoft Visual Studio 9.0\\VC\\redist\\x86\\Microsoft.VC90.CRT
如果仅仅是安装了 Microsoft Visual C++ 2008 Redistributable Package
, 这些文件路径一般类似于 C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_50934f2ebcb7eb57
注解
如果你的python应用用了一些特殊的库,比如PyQt,可能会遇到一些问题,参见 Working with Various Packages and Modules
python与其他语言交互¶
Page Status: | Development |
---|---|
Last Reviewed: |
python的一大特性就是能和很多语言方便的交互,所以python经常被称为胶水语言。
使用 ctypes
访问第三方C动态库 [1] [2]¶
Windows平台¶
在32bit的Windows系统上,对 __cdecl
和 __stdcall
声明的函数,编译时函数名会使用不同的命名规则 [6]
比如编译如下C代码:
int _cdecl f (int x) { return 0; }
int _stdcall g (int y) { return 0; }
int _fastcall h (int z) { return 0; }
32bit的编译器会输出:
_f
_g@4
@h@4
cdll使用 __cdecl
声明函数, windll和oledll使用 __stdcall
声明函数
oledll比一般的windll额外指定了返回值的类型,为 HRESULT
,见 OleDLL
所以ctypes为windows系统提供了三种dll的类来区分使用,windows上既可以通过属性来访问dll,也可以通过 cdll.LoadLibrary
来访问:
>>> from ctypes import *
>>> print windll.kernel32
<WinDLL 'kernel32', handle ... at ...>
>>> print cdll.msvcrt
<CDLL 'msvcrt', handle ... at ...>
>>> libc = cdll.msvcrt
>>>
使用 comtypes
访问COM组件 [7]¶
windows平台上大部分模块基于COM技术,对COM的支持使得python能支持大部分的windows上的模块
在没有comtypes的情况下,利用ole.dll中的C函数也可以实现对COM组件的访问 [8] ,但需要自己处理COM组件和python之间的数据结构的差异,编程效率低
下面是comtypes中访问COM组件的代码节选:
#COM functions are in ole32.dll
from ctypes import oledll
_ole32 = oledll.ole32
_ole32_nohresult = windll.ole32
#init COM
_ole32.CoInitializeEx(None, None)
#create COM object instance
_ole32.CoCreateInstance(byref(clsid), punkouter, clsctx, byref(iid), byref(p))
#use COM functions
p.func1()
p.func2()
#deinit COM
_ole32_nohresult.CoUninitialize()
注解
COM组件使用regsvr32.exe注册时,将COM组件的信息(dll的信息,clsid,progid)写入注册表,需要使用时再根据clsid或progid从注册表中查找dll的信息 [9]
既可以直接使用regedit来查看注册的COM组件信息,也可以用专门的工具oleview.exe (in WDK)来查看
利用comtypes,可以用纯python代码实现对所有类型COM组件的访问(custom类型的,支持dispatch接口类型的),并且支持编写COM组件
注解
pywin32
不支持对custom类型的COM组件的访问
通过clsid,progid,来访问COM组件¶
如果我们知道了COM组件的clsid或progid,可以通过comtypes.client中的CreateObject函数来访问COM组件:
instance = CreateObject(clsid/progid)
通过typelib,dll文件来访问COM组件¶
如果我们不知道COM组件的clsid或progid,但知道dll文件的路径,我们可以使用oleview.exe来查看clsid,或者可以通过comtypes.client中的GetModule函数来生成python binding,然后从python binding中查找clsid和iid:
module = GetModule(typelib/dll/exe)
dir(module)
构建自己的c/c++扩展¶
一个最简单的c扩展,来自python源代码PC/example_nt/example.c:
#include "Python.h"
static PyObject *
ex_foo(PyObject *self, PyObject *args)
{
printf("Hello, world\n");
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef example_methods[] = {
{"foo", ex_foo, METH_VARARGS, "foo() doc string"},
{NULL, NULL}
};
PyMODINIT_FUNC
initexample(void)
{
Py_InitModule("example", example_methods);
}
在python中调用此模块的代码如下:
>>> import example
>>> example
<module 'example' from 'example.pyd'>
>>> example.foo()
Hello, world
>>> help(example.foo)
Help on built-in function foo in module example:
foo(...)
foo() doc string
从中可以看出,一个基本的c扩展包含以下部分:
- 最开始
#include "Python.h"
- 模块方法实现
- 模块接口定义
- 模块初始化函数
更多内容见 Extending Python with C or C++ [4]
注解
需要实现更复杂的c扩展,可以利用python源代码中Modules/xxmodule.c作为模板
用 distutils
编译c/c++扩展¶
当完成c/c++扩展的编写,为了能让python能够顺利访问扩展中的成员,我们还需要将c/c++源码编译成动态库.so/.pyd [3]
同样看一个简单的sample,来自python源代码PC/example_nt/setup.py:
from distutils.core import setup, Extension
example_mod = Extension('example', sources = ['example.c'])
setup(name = "example",
version = "1.0",
description = "A sample extension module",
ext_modules = [example_mod],
)
扩展的编译是通过distutils中的Extension类来完成的,详见 [10]
注解
如果在windows上编译遇到 error: Unable to find vcvarsall.bat
则需要设置环境变量,将 VS90COMNTOOLS
设置为VS的Tools路径
比如, 如果你安装的是2013版 SET VS90COMNTOOLS=%VS120COMNTOOLS%
向c/c++程序里面内嵌python代码¶
示例代码:
#include <Python.h>
int
main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
Py_Finalize();
return 0;
}
简单内嵌步奏:
- 将程序名传入python解析器,使用函数Py_SetProgramName()
- 初始化python解析器,使用函数Py_Initialize()
- 执行python代码或文件,使用函数PyRun_SimpleString(),PyRun_SimpleFile()
- 关闭python解析器
参考¶
[1] | http://starship.python.net/crew/theller/ctypes/ |
[2] | https://docs.python.org/2/library/ctypes.html |
[3] | https://docs.python.org/2/faq/windows.html#is-a-pyd-file-the-same-as-a-dll |
[4] | https://docs.python.org/2/extending/index.html |
[5] | http://blog.vrplumber.com/b/2007/07/21/ctypes-for-c-is/ |
[6] | http://en.wikipedia.org/wiki/Name_mangling#C_name_decoration_in_Microsoft_Windows |
[7] | https://pythonhosted.org/comtypes/ |
[8] | http://www.codeproject.com/Articles/13601/COM-in-plain-C#C |
[9] | https://msdn.microsoft.com/en-us/library/windows/desktop/ms683954(v=vs.85).aspx |
[10] | https://docs.python.org/2/distutils/apiref.html#distutils.core.Distribution |
用reStructuredText编写文档¶
Page Status: | Development |
---|---|
Last Reviewed: |
reStructuredText是一个纯文本的标记语言,可被用于python内嵌文档编写,网页编写或者用来写文章。
Python库docutils实现了对reStructuredText标记语言的解析支持,并能将其转化成其他常用的文档格式,如HTML,Latex,PDF
注解
reStructureText参考资料:
reStructuredText标记¶
reStructuredText标记内嵌注意¶
当在文本中使用reStructuredText的标记和对单独词组使用reStructuredText的标记有所不同,需要有一些特别的注意点。见 reStructuredText内嵌语法
- 起始reStructuredText标记之前必须是:
- 空格
- ASCII字符 - : / ‘ ” < ( [ {
- a non-ASCII punctuation character with Unicode category Pd (Dash), Po (Other), Pe (Close), Pf (Final quote), or Pi (Initial quote)
- 起始reStructuredText标记之后必须是一个非空格字符
- 结尾reStructuredText标记之后必须是:
- 空格
- ASCII字符 - : / ‘ ” < ( [ {
- a non-ASCII punctuation character with Unicode category Pd (Dash), Po (Other), Pe (Close), Pf (Final quote), or Pi (Initial quote)
- 结尾reStructuredText标记之前必须是一个非空格字符
- 如果起始起始reStructuredText标记之前有ASCII字符 ‘ ” < ( [ {或者a character with Unicode character category Ps, Pi, or Pf则之后不能直接接ASCII字符’ ” ) ] } > or the categories Pe, Pf, or Pi
- 起始reStructuredText标记和结尾reStructuredText标记之间至少有一个字符
- 反斜杠字符会取消reStructuredText标记的语义
reStructuredText常见语法¶
链接相关语法¶
语法 | 输出 | 说明 | ||
`python <http://www.python.org>`_ | python | 内嵌外部链接 | ||
pypi_ .. _pypi: https://pypi.python.org/pypi |
pypi | 外部链接1 | ||
`python docs`_ .. _`python docs`: http://docs.python.org |
python docs | 外部链接2 | ||
`python intro`_ .. _`python intro`: python introducation |
python introducation |
内部链接 | ||
`anonymous`__ __ http://www.python.org/ |
anonymous | 匿名链接 | ||
[1]_ .. [1] this is a footnote |
|
脚注 | ||
[citation]_ .. [citation] this is a citation |
|
引用 |
段落相关语法¶
普通段落¶
语法 | 输出 | 说明 |
This is a paragraph. Paragraphs line up at their left edges, and are normally separated by blank lines. |
This is a paragraph. Paragraphs line up at their left edges, and are normally separated by blank lines. |
段落以空行分隔 |
标题¶
语法 | 输出 | 说明 |
parts ########### chapters *********** sections ========= subsections ------------ subsubsections ^^^^^^^^^^^^^^^ paragraphs """"""""""""" |
partschapterssectionssubsectionssubsubsectionsparagraphs |
标题由底部(或底部和顶部)连续的一组ASCII非字母数字的字符标识, 标题级别自动分配,最先出现的标题级别较高, 推荐使用标识字符有"= - ` : ' " ~ ^ _ * + # < >"。 Sphinx推荐在python文档中使用如下的规则: |
列表¶
列表的开始和结束各需要一个空行,列表中间的空行是可有可无的
语法 | 输出 | 说明 | ||||||||||
- This is item 1 - This is item 2 |
|
Bullet Lists | ||||||||||
3. This is the first item 4. This is the second item 5. Enumerators are arabic numbers, single letters, or roman numerals 6. List items should be sequentially numbered, but need not start at 1 (although not all formatters will honour the first index). #. This item is auto-enumerated |
|
Enumerated Lists | ||||||||||
what Definition lists associate a term with a definition. how The term is a one-line phrase, and the definition is one or more paragraphs or body elements, indented relative to the term. Blank lines are not allowed between term and definition. |
|
Definition Lists | ||||||||||
:Authors: Tony J. (Tibs) Ibbs, David Goodger (and sundry other good-natured folks) :Version: 1.0 of 2001/08/08 :Dedication: To my father. |
Authors: Tony J. (Tibs) Ibbs, David Goodger (and sundry other good-natured folks) Version: 1.0 of 2001/08/08 Dedication: To my father. |
Field Lists | ||||||||||
-a command-line option "a" -b file options can have arguments and long descriptions --long options can be long also --input=file long options can also have arguments /V DOS/VMS-style options too |
|
Option Lists |
文字块¶
注解
文字块中的特殊字符不会被解析和替代, 所有的特殊字符,空格和换行符会被保留。
语法 | 输出 | 说明 |
``内嵌文字块`` |
内嵌文字块 |
内嵌块经常用于显示一段短小的代码 |
只有双引号``::``的段落表明接下来的所有缩进的/引用的文字都是一个文字块 :: 所有的reStructureText的转义字符如空格,换行,空行 (like *this* or \this) 都不会被转义,会被直接保留。 结果中不会保留双引号 双引号``::``可以位于一个段落的最后, 如果双引号``::``后面接空格,双引号会被忽略, 如果双引号``::``后面接文字,双引号会变成一个单引号, 比如:: 这样很方便 当缩进恢复正常,文字段结束, 所以我们可以在文字段中使用不同的缩进:: 8个空格的缩进 4个空格的缩进 2个空格的缩进 也使用引用来标识文字块,合法的引用符号有:: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ 利用引用标识的文字块示例:: > 引用的文字块第一行 > 引用的文字块第二行 |
只有双引号``::``的段落表明接下来的所有缩进的/引用的文字都是一个文字块 所有的reStructureText的转义字符如空格,换行,空行 (like *this* or \this) 都不会被转义,会被直接保留 结果中不会保留双引号 双引号``::``可以位于一个段落的最后 如果双引号``::``后面接空格,双引号会被忽略 如果双引号``::``后面接文字,双引号会变成一个单引号 比如: 这样很方便 当缩进恢复正常,文字段结束 所以我们可以在文字段中使用不同的缩进: 8个空格的缩进 4个空格的缩进 2个空格的缩进 也使用引用来标识文字块,合法的引用符号有: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ 利用引用标识的文字块示例: > 引用的文字块第一行 > 引用的文字块第二行 |
段落块 两个冒号加一个空行后面所有的缩进的段落都是块 |
| Line blocks are useful for addresses, | verse, and adornment-free lists. | | Each new line begins with a | vertical bar ("|"). | Line breaks and initial indents | are preserved. | Continuation lines are wrapped portions of long lines; they begin with spaces in place of vertical bars. |
Line blocks are useful for addresses, verse, and adornment-free lists. Each new line begins with a vertical bar ("|"). Line breaks and initial indents are preserved. Continuation lines are wrapped portions of long lines; they begin with spaces in place of vertical bars. |
行块 |
注释¶
没有有效标记(如脚注)的直解标记(.. )文本块就是注释(参考) 例如:
可以用缩进文本来进行多行注释:
..
This whole indented block
is a comment.
Still in the comment.
注解
注释内容在输出中可能不可见
代码块¶
可以用如3.2.4节文字块的方法来标识代码块:
示例:
python code::
#python code
def one_function():
pass
输出:
python code:
#python code
def one_function():
pass
指令语法¶
指令是reStructuredText用来在不改变/新增已有语法的基础上,扩展新的特性的一种机制。
reStructuredText标准指令文档 罗列了所有的标准指令
其他的指令由各自的解析器自己定义,比如sphinx就支持很多 自定义的指令
指令语法示意:
+-------+------------------+
| ".. " | 指令类型 "::" 指令 |
+-------+ 块 |
| |
+------------------+
指令块由指令符后面所有缩进内容组成,指令块可以包含三部分:
- Directive arguments
- Directive options
- Directive content
Directive arguments和Directive options紧接着指令。Directive content和它们之间用空行分隔。
不同的指令对指令块的要求不同,如果提供的指令块不符合要求,会导致错误
下面介绍一些常用的标准指令和sphinx扩充的指令。
reStructuredText标准指令¶
提醒指令¶
提醒指令 ,包含”attention”, “caution”, “danger”, “error”, “hint”, “important”, “note”, “tip”, “warning”, “admonition”
示例:
.. attention::
Attention Please!
输出 :
注意
Attention Please!
image指令¶
图片指令 向输出中插入指定图片
示例:
.. image:: images/happy_dog.jpg
:heigsht: 200px
:width: 300 px
:scale: 50 %
:alt: 快乐的狗狗
输出 :

role指令¶
role指令 建立并向解析器注册了role类型,所有mark成这种role类型的文本都会被解析器以这种类型解析。
reStructureText定义了一些 标准role类型
sphinx也扩充了 一些role类型
自定义role类型示例 :
使用role指令动态定义一种文本解析方式:
.. role:: custom
文本中使用custom类型的文本会被按照custom类型来解析:
An example of using :custom:`interpreted text`
结果会类似于这样:
<paragraph>
An example of using
<inline classes="custom">
interpreted text
注解
role指令必须先定义,再使用
基于已有role类型的示例:
可以基于已有的role类型来定义新的role类型,新的role类型将是已有类型的一个子集
定义:
.. role:: raw-role(raw)
:format: html
使用:
用html实现 :raw-role:`<strong>加粗的文本</strong>`
输出:
用html实现 加粗的文本
sphinx扩充的指令¶
sphinx对reStructureText的指令有所扩充,见 Sphinx Markup Constructs
用sphinx组织文档¶
Page Status: | Development |
---|---|
Last Reviewed: |
sphinx是一个文本builder,能将一组reStructureText文档转换成其他格式(HTML, LaTex),能自动解析处理reStructureText标记。
安装sphinx¶
建议通过easy_install或pip来安装sphinx,能够自动处理依赖,简单迅速。
使用sphinx¶
sphinx提供了工具来简化了文档工程的配置和生成,使得用户能够更加专注于文档的内容。
对于一般的文档工程,使用sphinx通常包含有几个步奏, 见 sphinx初尝
- 使用工具sphinx-quickstart快速配置文档资源
- 修改index.rst来定义文档结构
- 使用reStructureText添加文档内容
- build,输出结果
sphinx的更多内容¶
上面4个步奏已经可以满足大部分一般用户的需求,如果用户需要使用sphinx的更多功能(更多标记,更多扩展,定制模板),则需要对sphinx有更多的了解。
sphinx域¶
sphinx域是为某些语言输出提供特定的语法, 内置的支持包含python,c,c++,javascript,reStructureText。见 sphinx domain
比如我想输出一个python的函数
想要得到的效果:
format_exception(etype, value, tb[, limit=None])
Format the exception with a traceback.
Parameters: •etype – exception type
•value – exception value
•tb – traceback object
•limit (integer or None) – maximum number of stack frames to show
Return type: list of strings
在文档中的写法:
.. py:function:: format_exception(etype, value, tb[, limit=None])
Format the exception with a traceback.
:param etype: exception type
:param value: exception value
:param tb: traceback object
:param limit: maximum number of stack frames to show
:type limit: integer or None
:rtype: list of strings
配置sphinx¶
sphinx的一些技巧¶
python debug¶
Page Status: | Development |
---|---|
Last Reviewed: |
pdb¶
python自带的调试器,使用 python -m pdb myscript.py
或者 import pdb; pdb.set_trace()
进入调试模式(post-mortem debugging)
debug python code with gdb¶
- pdb可以解决大部分python调试的需求,但是在一些复杂场景下,需要更强大的工具.
- 调试正在运行的process
- 调试可能hng的程序
- 调试多线程
参考:
https://wiki.python.org/moin/DebuggingWithGdb
remote debug¶
remote debug一般是IDE中提供的功能, 对于pycharm, 参考:
https://www.jetbrains.com/help/pycharm/2017.1/remote-debugging.html#6