导航:首页 > 编程语言 > python静态代码检查工具

python静态代码检查工具

发布时间:2022-10-17 05:32:15

A. python怎么使用cython

1. Cython是什么?

它是一个用来快速生成Python扩展模块(extention mole)的工具

语法是Python和c的混血

Cython作为一个Python的编译器,在科学计算方面很流行,用于提高Python的速度,通过OpenMPI库还可以进行吧并行计算。

2. Cython安装(Windows)

我的环境是win7 x64, python27, vs2010

安装的基础是有一个c编译器(这里以vs2010为例)

从http://cython.org下载安装包,解压到一目录,进入该目录,在cmd命令行中执行

python setup.py install

注:执行过程可能遇到问题:Windows下pip安装包报错:Microsoft Visual C++ 9.0 is required Unable to find vcvarsall.bat

解决方案:下载Microsoft Visual C++ Compiler for Python 2.7,点击直接安装即可。

3. 例子

例3.1:入门

创建hello.pyx,内容如下

def say_hello():
print "Hello World!"

创建setup.py,内容如下

from distutils.core import setup
from Cython.Build import cythonize
setup(name = 'Hello world app',
ext_moles = cythonize("hello.pyx"))

编译Cython代码

step1: 把.pyx文件被Cython便以为.c文件
step2: 把.c文件编译为可导入的使用模块.so(Windows下为.pyd)文件

1
2

python setup.py build
python setup.py install

注:可能出现问题:Unable to find vcvarsall.bat

原因:Python 2.7 会搜索 Visual Studio 2008.如果你电脑上没有这个版本的话就会报错。

如果装的是vs2010,那么在cmd命令行中执行

1

SET VS90COMNTOOLS=%VS100COMNTOOLS%

如果装的是vs2010,那么在cmd命令行中执行

1

SET VS90COMNTOOLS=%VS110COMNTOOLS%

执行

1
2
3

>>> import hello
>>> hello.say_hello()
Hello World!例3.2 通过静态类型提高速度

在Cython中可以通过标记静态类型来提高速度,凡是标记为静态类型的部分都会将动态语言类型变为简单的c代码,从而提速。

但是如果滥用静态类型,会降低可读性,甚至因类型设置不当导致错误类型检查造成速度降低。

例3.2.1 静态类型变量

Python原生态代码

compute.pyx

def f(x):
return x ** 2 - x
def integrate_f(a, b, N):
s = 0
dx = (b - a) / N
for i in range(N):
x += f(a + i * dx)
return s * dx

setup.py

from distutils.core import setup
from Cython.Build import cythonize
setup(
name = 'Hello world app',
ext_moles = cythonize("compute.pyx"),
)

test.py

import compute
import time
starttime = time.clock()
compute.integrate_f(3.2, 6.9, 1000000)
endtime = time.clock()
print "read: %f s" %(endtime - starttime)

执行

1
2
3

python setup.py build
python setup.py install
python test.py

结果

1

read: 0.332332 s

使用静态变量替换后的代码

compute2.pyx

def f(double x):
return x ** 2 - x
def integrate_f(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b - a) / N
for i in range(N):
s += f(a + i * dx)
return s * d

setup2.py

from distutils.core import setup
from Cython.Build import cythonize
setup(
name = 'Hello world app',
ext_moles = cythonize("compute2.pyx"),
)

test2.py

import compute2
import time
starttime = time.clock()
compute2.integrate_f(3.2, 6.9, 1000000)
endtime = time.clock()
print "read: %f s" %(endtime - starttime)

执行

1
2
3

python setup.py build
python setup.py install
python test.py

结果

1

read: 0.109200s

结论

该测试用例,使用静态类型速度是不使用静态类型的3倍。

例3.2.2 静态类型函数

把compute2.pyx中的函数变为

cdef double f(double x):
return x ** 2 - x
def integrate_f(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b - a) / N
for i in range(N):
s += f(a + i * dx)
return s * dx

结果

1

read: 0.084859 s

结论:比例子3.2.1速度又快了

例3.3 调用C函数

cdef extern from "math.h":
double sin(double)
double cos(double)

cpdef double Sin(double x):
return sin(x)

cpdef double Cos(double x):
return cos(x)

cpdef: 对于Python可使用的函数使用(为了使得在以后的Python程序中调用Sin,Cos函数,用cpdef,而不用cdef)
cdef: 对于C可使用的函数使用

请注意,上面的代码声明了 math.h 里的函数,提供给 Cython 使用。C编译器在编译时将会看到 math.h 的声明,但 Cython 不会去分析 math.h 和单独的定义。

B. C++静态代码扫描工具都有哪些

工具非常多,各个工具通常会以插件的形式嵌入在各种IDE中,本人目前最偏爱cpplint,其实是就一个python脚本,帮助检查是否符合GoogleC++Style的标准规范。

C. python的ide有哪些

分享的这几个IDE工具希望会对你的开发有帮助。

1.Pyscripter

Pyscriptor是一个开源的Python集成开发环境,很富有竞争力,同样有诸如代码自动完成、语法检查、视图分割文件编辑等功能。

2. Wing

Wing是一个Python语言的超强IDE,适合做交互式的Python开发.Wing IDE同样支持自动代码完成、代码错误检查、开发技巧提示等,而且Wing IDE也支持多种操作系统,包括Windows、Linux和Mac OS X。

3. Emacs

Emacs是一个可扩展的文本编辑器,同样支持Python开发.Emacs本身以Lisp解释器作为其核心,而且包含了大量的扩展。

4. Pycharm

Pycharm是一个跨平台的Python开发工具,是JetBrains公司的产品.其特征包括:自动代码完成、集成的Python调试器、括号自动匹配、代码折叠.Pycharm支持Windows、MacOS以及Linux等系统,而且可以远程开发、调试、运行程序。

5. Sublime Text

SublimeText也是适合Python开发的IDE工具,SublimeText虽然仅仅是一个编辑器,但是它有丰富的插件,使得对Python开发的支持非常到位。

6. Vim

Vim是一个简洁、高效的工具,也适合做Python开发。

7. Komodo Edit

Komodo Edit是一个免费的、开源的、专业的Python IDE,其特征是非菜单的操作方式,开发高效。

8. Eclipse with PyDev

Eclipse+PyDev插件,很适合开发Python Web应用,其特征包括自动代码完成、语法高亮、代码分析、调试器、以及内置的交互浏览器。

很多时候,一个好的工具能够对于编程的辅助作用是非常大的,无论是在python培训期间还是工作之后,都脱离不了各种IDE工具应用。

D. python第三方库为什么

Python第三方库几乎都可以在github或者 pypi上找到源码。源码包格式大概有zip 、 tar.zip、 tar.bz2。解压这些包,进入解压好的文件夹,通常会有一个setup.py的文件。打开命令行,进入该文件夹。运行以下命令,就能把这个第三库安装到系统里:

Python

python setup.py install
1
python setup.py install
或者借助pip,则不需要解压:pip install package.zip

E. 风变编程的Python课程学完效果如何

一、Python简介

Python是一种用来编写应用程序的高级程序设计语言,TIOBE程序语言排行榜2015年12月的排名如下:

Python实现强势逆袭,而且我相信,随着时间的推移,国内Python语言未来前景也是一片向好。

Python的特点是优雅简单,易学易用(虽然我感觉还是有一些概念不容易理解),Python的哲学是尽量用最少的,最简单易懂的代码实现需要的功能。Python适宜于开发网络应用,脚本写作,日常简单小工具等等。Python的缺点是效率较低,但是在大量的场合效率却不是那么重要或者说Python不是其性能瓶颈,所以不要太在意。其次是2.x-3.x的过渡使得许多3.x还缺少很多2.x下的模块,不过也在完善中。其次就是源代码无法加密,发布Python程序其实就是发布源代码。

二、基础语法要点

1.如果一个字符串中有许多需要转义的字符,而又不想写那么多'',那么可以用 r'...' 表示 '...'内的内容不转义。

2.Python可用'''...'''来表示多行内容,如:

123456

>>>print('''line1line2line3''')line1line2line3

3.Python的逻辑运算and, or, not 分别对应C语言中的&&, ||, !.

4.Python的整数与浮点数大小都没有范围。

5.Python中除法有两种: '/'除出来必是浮点数, '//'除出来是整数,即地板除。

6.Python中一切皆引用。每个对象都有一个引用计数器(内部跟踪变量)进行跟踪,引用计数值表示该对象有多少个引用,当初次产生赋给变量时,引用计数为1,其后没进行下列行为中的任意一种都会增加引用计数:

123

赋值: a=b用作函数参数传递: func(a)成为容器对象的一个元素: lis=[1,2,a]

以下任意一种行为都会减少引用计数:

1234

del销毁:dela变量另赋给其他对象:a=False对象从容器中删除: lis.remove(a)身在的容器被销毁:dellis

7.深拷贝与浅拷贝的概念与对比,有点复杂,看这篇文章

8.list,tuple和dict,set

list:为列表,是一个有序集合,类似于数组但又比数组功能强大,可以随时append,pop元素,下标从0开始,且下标为加n模n制,即lis[-1] = lis[len-1],下标范围[-len,len-1].

tuple:为元组,类似于list,但list为可变类型,而tuple不可变,即没有append,pop等函数。一个建议是为了安全起见,能用tuple代替list尽量用tuple。如果tuple只有一个元素,要写成如(1,)以避免歧义。

dict:字典类型,存放key-value键值对,可以根据key迅速地找出value,当然,key必须是不可变类型,如下是错误的:

12345

>>> dic={[1,2]:'value'}Traceback (most recent call last):File"<pyshell#10>", line1,in<mole>dic={[1,2]:'value'}TypeError: unhashabletype:'list'

list与dict的优劣对比:

1234567

dict:1.插入,查找速度快,跟key的数目无关2.需占用大量内存,内存浪费严重list:1.插入,查找速度慢,O(n)的复杂度,随元素个数增加而增加2.占用内存小

dict内部存放的顺序和key放入的顺序是没有关系的

set:set与dict类似,相当于只有key没有value的dict,每个key不同,set间有 &, | 等操作对应集合的交,并操作。

三、函数

1.函数是对象,函数名即是指向对应函数对象的引用,所以可以将函数名赋给一个变量,相当于给函数起一个‘别名’。

123

>>> mmm=max>>> mmm(1,2,3)3

2.Python函数可以返回”多个值“,之所以打引号,是因为实际上返回的多个值拼成了一个元组,返回这个元组。

3.定义默认参数需要牢记:默认参数必须指向不变对象。否则第一次调用和第二次调用结果会不一样,因为可变的默认参数调用后改变了。

4.可变参数:传入的参数个数是可变的,可以是0个或多个。可变参数会将你传入的参数自动组装为一个tuple。在你传入的list或tuple名字前加一个 * 即说明传入的是可变参数。习惯写法为*args。

5.关键字参数:传入0个或多个含参数名的参数,这些参数被自动组装成一个dict。习惯写法**kw,如**a表示把a中所有的键值对以关键字参数的形式传入kw,获得一个dict,这个dict是a的一份拷贝,对kw改动不会传递到a

6.命名关键字在函数定义中跟在一个*分割符后,如

12

deffunc(a,b,*,c,d):pass

c,d为命名关键字参数,可以限制调用者可以传入的参数名,同时可以提供默认值。

7.参数定义顺序:必选参数,默认参数,可变参数/命名关键字参数,关键字参数。

8.切片操作格式为lis[首下标:尾下标:间隔],如果都不填,即lis[::]则代表整个容器lis

9.用圆括号()括起来一个列表生成式创建一个生成器generator,generator保存生成算法,我们可以用next(g)取得生成器g的下一个返回值。生成器的好处就是我们不需要提前生成所有列表元素,而是需要时再生成,这在某些情况下可以节省许多内存。算法也可以不是列表生成式而是自定义函数,只需在函数定义中包含yield关键字。

10.map()和rece(): 二者都是高阶函数。map()接收两个参数,一个是函数,一个是Iterable序列,map将传入的函数依次作用在序列每一个元素上,并把结果作为新的Iterator返回。rece()类似累积计算版的map(),把一个函数作用在一个序列上,每次接收两个参数,将结果继续与序列的下一个元素做累积计算。

利用map和rece编写一个str2float函数,如把字符串'123.456'转换成浮点数123.456:

123456789101112131415

(s):deff1(x,y):returnx*10+ydefchar2num(s):return{'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s]deff2(x,y):returnx*0.1+ya,b=s.split('.')print('a=',a)print('b=',b)returnrece(f1,map(char2num,a))+0.1*rece(f2,map(char2num,b[::-1]))print('str2float('123.456') =', str2float('123.456'))

11.fliter()函数过滤序列,类似于map()作用于每一元素,根据返回值是True或者False决定舍弃还是保留该元素。函数返回一个Iterator。

12.sorted()函数可实现排序,类似于C++库中的sort()函数,但是比其更加简洁,语法为sorted(lis,key=func,reverse=T/F)

key函数可实现自定义的排序规则,reverse表示升序还是降序。

13.一个函数可以返回一个函数,但是返回时该函数并未执行,所以返回函数中不要引用任何可能发生变化的变量,否则会出现逻辑错误。

14.装饰器(decorator): 当需要增强函数的功能却不希望修改函数本身,那么可以采用装饰器这种运行时动态增加功能的方式,增加的功能卸载装饰器函数中。如在执行前后打印'begin call'和'end call',可以这样做:

12345678910111213141516

importfunctoolsdeflog(func):@functools.wraps(func)#为了校正函数签名,最好写上defwrapper(*args,**kw):print('begin call')f=func(*args,**kw)print('end call')returnfreturnwrapper@logdefhah():print('hahahaha')hah()

123

begin callhahahahaend call

15.偏函数: functools.partial(),作用是将一个函数的某些参数固定住,作为新函数的参数,即固定住该参数,返回一个新函数,使调用更简单。

四、面向对象编程

1.Python实例变量可以自由地绑定任何属性

2.为了不让内部属性不被外部访问,在属性的名称前加上两个下划线__,这样就变成了一个私有变量(private),注意,不能直接访问不代表一定不能访问,事实上,加双下划线后Python就会将其改名为‘_class名__name’,所以还是可以这样来访问这个‘私有’变量。

3.对于静态语言,如果要求传入一个class类型的对象,那么传入的对象必须是class类型或者其子类,否则将无法调用class中的方法,而Python这样的动态语言有‘鸭子类型’一说,即不一定要传入class类型或其子类,而只要保证传入的对象中有要使用的方法即可。

4.如果想要限制实例可以绑定的属性,那么在定义class时定义一个__slots__变量即可,例如:

12

classStudent(object):__slots__=(‘name’,’age’)

注意,__slots__限制的属性对当前类实例起完全限制作用,且与子类共同定义其__slots__,也就是说子类可以定义自己的__slots__,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__,即并集。

5.@ property装饰器可以使一个getter方法变成属性,如果方法名为me,那么@me.setter装饰器则可使一个setter方法变成属性。这样可以使代码更简短,同时可对参数进行必要的检查。

6.通过多重继承,可使子类拥有多个父类的所有功能。

7.在类中__call__方法可使实例对象像函数那样直接调用,作用即是该方法定义的过程。

8.ORM(Object Relational Mapping 对象关系映射),就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表。ORM的实现需要通过metaclass元类修改类的定义。元类可以改变类创建时的行为。

五、调试

1.Python调试方法:

(1)直接打印

(2)断言

(3)pdb

(4)IDE

六、IO编程

1.序列化: 把变量从内存中变成可存储或传输的过程称之为序列化。Python用pickle模块实现序列化。序列化之后,就可以把序列化后的内容存储到磁盘上或者通过网络进行传输。pickle.mps()将对象序列化成一个bytes,而pickle.loads()可以根据bytes反序列化出对象。

2.pickle虽好,但是它专为Python而生,所以要在不同语言间传递对象,最好还是xml或者json,而json表示格式是一个字符串,更易读取,且比xml快,所以更加适宜于对象序列化。Python内置了json模块,相应方法仍然是mps()和loads()。

3.但是在默认情况下,有些对象是无法序列化的,所以我们有时还需要定制转换方法,告诉json该如何将某类对象转换成可序列为json格式的{}对象。如下即是一个转换方法:

123456

defmantodict(std):return{'name': std.name,'age': std.age,'id': std.id}

七、进程与线程

1.Python用mutiprocessing模块来实现多进程。

2.如果要大量创建子进程,可以使用进程池:

1

frommultiprocessingimportPool

示例如下:

12345678

....p=Pool(4)foriinrange(5):p.apply_async(long_time_task, args=(i,))print('Waiting for all subprocesses done...')p.close()p.join()print('All subprocesses done.')

要使用进程池需新建Pool对象,对Pool对象调用join()使等待池中所有子进程运行完毕,调用join()方法之前必须调用close(),且此后无法再新加子进程。

3.使用subprocess模块可以方便的启动并管理一个子进程,控制其输入输出。

4.进程间通信使用Queue,Pipes实现。

5.threading模块管理线程。threading.lock()创建线程锁,防止同时访问互斥资源造成的错误,示例如下:

1234567

lock=threading.Lock()...lock.acquire()...change(mutex)...lock.release()

6.ThreadLocal可以解决参数在一个线程中各个函数之间互相传递的问题。

7.managers模块实现分布式进程。

八、正则表达式与常用内建模块

1.re模块进行正则表达式编译和匹配,如果该表达式需要匹配很多次,那么最好进行编译从而大大节省时间。

正则表达式匹配邮箱例子:

12345678910

importrehah=re.compile('[0-9a-zA-Z]+[.[0-9a-zA-Z]+]*@[0-9a-zA-Z]+.[a-z]{2,3}')print(hah.match('[email protected]').group())print(hah.match('[email protected]').group())i=1whilei <10:r=input('请输入邮箱:')print(hah.match(r).group())i=i+1

2.datetime模块进行日期和时间的处理,每一个时间对应一个timestamp,我们把1970年1月1日 00:00:00 UTC+00:00时区的时刻称为epoch time,记为0(1970年以前的时间timestamp为负数),当前时间就是相对于epoch time的秒数,称为timestamp。字符串和datetime也可以相互转换,采用strptime()方法,字符串转换为datetime时需要设定一个识别格式,其中

1

%Y-%m-%d%H:%M:%S

分别表示年-月-日 时-分-秒。

从datetime得出月份,星期等字符串用strftime()方法,其中:

1

%a,%b%d%H:%M

分别表示星期, 月份 日期 时:分。

示例:

12345678910

fromdatetimeimportdatetimer='2015-11-23 12:01'dt=datetime.strptime(r,'%Y-%m-%d %H:%M')print(dt)week=dt.strftime('%a %b %d, %H:%M')print(week)2015-11-2312:01:00Mon Nov23,12:01

3.collections是Python内建的一个集合模块,提供了许多有用的集合类。

4.Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。

5.struct模块用来解决bytes和其他二进制数据类型的转换。

6.Python的hashlib提供了常见的哈希算法,如MD5,SHA1等等。hashlib实现简单登录:

importhashlibdb={'michael':'','bob':'','alice':''}defget_md5(ostr):md5=hashlib.md5()md5.update(ostr.encode())returnmd5.hexdigest()deflogin(user, password):r=get_md5(password)fornameindb:ifdb[name]==r:returnTruereturnFalseprint(login('bob','abc999'))True

7.Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数。

8.urllib提供了一系列用于操作URL的功能。如GET,POST...

9.PIL(Python Imaging Library Python图像库)是一个强大的图像处理标准库,功能强大却又简单易用。现在的名字叫做Pillow。可以如下安装Pillow:

1

pip3 install pillow

从下面生成数字验证码的程序可以窥其一斑:

九、网络编程和电子邮件

1.网络编程主要是TCP和UDP的编程,示例见【Python网络编程】利用Python进行TCP、UDP套接字编程

2.SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。Python内置一个poplib模块,实现了POP3协议,可以直接用来收邮件。由于现在绝大多数大型邮件服务商都采取了反垃圾邮件措施,所以这部分的简单实验并没有成功,还需进一步研究,等遇到具体情况再说。

3.Python内嵌了sqlite数据库,还可以自行安装连接mysql,MySQL是当前最流行的开源数据库,在行业内有着广泛的应用。

十、Web开发和异步IO

1.WSGI(Web Server Gateway Interface) 服务器网关接口。

2.Python web 开发框架:

-Flask:流行的Web框架

-Django:全能型Web框架

-web.py:一个小巧的Web框架

-Bottle:和Flask类似的Web框架

-Tornado:Facebook的开源异步Web框架

3.协程

F. 静态分析是指

经济领域概念
静态分析是一种分析经济现象的均衡状态以及有关的经济变量达到均衡状态所需要条件的分析方法。[1]而不考虑经济现象达到均衡状态的过程,它完全抽象掉了时间因素和具体的变化过程,是一种静止地、孤立地考察某种经济事物的方法。
网络


静态分析
经济领域概念
静态分析是一种分析经济现象的均衡状态以及有关的经济变量达到均衡状态所需要条件的分析方法。[1]而不考虑经济现象达到均衡状态的过程,它完全抽象掉了时间因素和具体的变化过程,是一种静止地、孤立地考察某种经济事物的方法。

中文名
静态分析
外文名
static analysis
指标
总量指标、相对指标、平均指标、标志变异指标等
应用
静态计算机科学、经济学、工程、力学、机械
释义
根据既定的外生变量值求得内生变量的分析方法
内涵
静态分析法是根据既定的外生变量值求得内生变量的分析方法,是对已发生的经济活动成果,进行综合性的对比分析的一种分析方法。

如研究均衡价格时,舍掉时间、地点等因素,并假定影响均衡价格的其他因素,如消费者偏好、收入及相关商品的价格等静止不变,单纯分析该商品的供求达于均衡状态的产量和价格的决定。简单地说就是抽象了时间因素和具体变动的过程,静止地孤立地考察某些经济现象。它一般用于分析经济现象的均衡状态以及有关经济变量达到均衡状态所需要的条件。

常用的静态分析法有:相对数分析法、平均数分析法、比较分析法、结构分析法、因素替换分析法、综合计算分析法、价值系数分析法等。

指标

G. python ide哪个好用

第一款:Eric6

Eric6是一个用Python编写的Python IDE,虽然它使用Qt5UI框架提供一个比IDLE复杂很多的UI。但是它的入门需要一些组件,因为Eric6不像传统的本地平台程序一样应用。它本质上是一个大的Python包和几个重量级依赖,例如Qt5的Python绑定。结果是:Eric6入门需要对Python包管理的理解,因此它不太可能会吸引初学者用户。从这方面而言,安装程序脚本会提供反馈,以便您知道哪些包需要提取和安装以完成设置过程。

Eric6有着设备齐全的显着特点。它包含现代的IDE,如类浏览、版本控制等通常的实用工具,但它也集成了对Python专用功能如unittest、PyLint和cx_freeze应用程序分发系统的支持。在Eric6创建的新项目,也可以建成PyQT4中/5GUI和控制台应用程序,因为底层库已安装,但额外的开发工具,如Qt的窗体设计器不包括在默认设置之内。

第二款:Wing IDE

作为Python程序员的智能开发环境,WingIDE强调专门为Python用户设计的功能集成。这不仅仅是跨代码库的重构功能或使用多个Python解释器。它还包括与许多流行的Python框架、包和第三方应用程序的详细集成。RaspberryPi用户也可以使用Wing IDE进行开发。不仅如此,Wing IDE是一个Python初学者非常好上手的工具。

第三款:Pyzo

Pyzo是一个小IDE,主要针对科学计算的用户,有一个小工具集:编辑器、交互式shell、文件浏览器、源结构浏览器和一些其他的设施。它主要用于与库的快速交互,您可以在Python的REPL中键入命令或执行单个文件,而不是正式的应用程序开发。在这个意义上,它不太适合那些想要创建应用程序,更适合那些想要使用Python作为工作台环境的人。

第四款:Thonny

Thonny,一个专门为初学者使用该语言设计的小型的IDE,是一个更加简单的选择。在Windows、Mac或Linux上可用,它还可以节省用户下载或配置的Python解释器。Python的最新版本与Thonny捆绑在一起,IDE默认开箱可用。也就是说,你可以随时交换任何其他Pythonruntime。

第五款:NINJA-IDE

作为一个独立的项目,NINJA-IDE可以像专业级开发工具,如ActiveState"s Komodo
IDE或PyCharm,不仅在开发人员的经验,而且它的功能集是由Python用户构建和为了Python用户构建的。例如,NINJA-IDE的首选项对话框有一个标签,用于选择在运行程序时使用的Python解释器,以及用户启动或设置解释器使用的所有各种命令行选项的复选框,这是非常方便地。IDE中的另一个选项卡默认显示为Migration2to3,它可以分析为Python2.X编写的脚本并提出建议。

第六款:VisualStudio Code

微软的简单和精益的代码编辑器从其支持不同语言的扩展的瀚海星系中获得力量。Python开发人员有一堆VisualStudioCode扩展,但最流行,最容易,最重要的是DonJayamanne的扩展。它与每一个最新版本的Python保持同步,它集成了所有你想要的好东西的支持:代码片段、代码静态分析、自动完成与科学工具集成,如Jupyter、重构、单元测试、调试以及更多更多。

H. sublime text 怎么添加python

Sublime Text 3 (ST3) 是一个轻量级的跨平台文字编辑器,尤以其轻快的速度,易用性和强大的社区支持而着称。它一经面世便被认为是一个杰出的编辑器,而它真正的强大之处在于你可以使用 Package Control 来增加它的功能以及可以进行各种自定义设置。
在本文章中,我们将会看到如何将 Sublime Text 打造成为 Python 的全栈开发环境(从前端到后端),如何通过自定义主题和插件来增强它的基本功能,并且还将会涉及到很多使 ST3 变得更加强大的常用的命令,特性以及快捷键。

本教程将假定你使用的是 Mac 电脑并且习惯于使用终端。如果你使用的是 Windows 或者 Linux 操作系统,本文涉及到的一些命令将有可能会有所不同,但是你应该仍然可以很容易地通过 Google 来获取到与本教程相关的解答。
在我们开始之前,让我们先讨论一下我所谓的”全栈”具体指的是什么。
在现在的 HTML5 以及移动设备开发中,Javascript 简直无处不在。是的,无处不在!仅仅使用 Python 基于某个框架比如 Django 或者 Flask 进行开发是不够的。如果你想从始至终真正的自己开发一个网站的话,你必须熟悉 Javascript(以及 Javascript 的一大堆的框架),REST API(含状态传输 API),响应式设计,当然还有 HTML 和 CSS,以及其他许多东西。现在让我们来面对一个问题:就像其他任何一个手艺人一样,为了成为一个最厉害的程序员,你的工具必须犀利,你的开发环境必须被打造成全栈开发——那就是我们马上将要开始的工作…
特性
让我们从 ST3 的一些默认特性开始着手吧…
Split Layouts 允许你将你的许多文件放到很多分割开来的视窗中。如果你正在进行以测试为目的的开发(将 Python 代码放在一个视窗中,而测试脚本放在另一个视窗中)或者正在进行前端开发(将 HTML 代码放在一个视窗里,CSS/Javascript 代码放在另一个视窗里)的时候将会非常有用。
Vintage Mode 让你能够在 ST3 中使用 vi 模式。
Chrome-like Tabs 让你在多个文件中切换变得更加方便。
Automatic loading of the last session 帮你自动打开你上次关闭的时候编辑器中所有打开的文件。我总是一直开着 ST3,而且其中打开着一大堆项目——当我重启电脑以后, 它能够自动帮我打开所有的这些文件和文件夹。
Code Snippets 允许你通过一两个简单的关键字就能写出一段常用的代码片(Snippets),从而增加你的生产效率。比如,你只需要打开一个文件,输入 “lorem” 然后敲击 tab 键,就会自动生成一段乱数假文(译者注: 一种用于测试文章或文字在不同字型、版型下看起来的效果等的文字)。又比如在 Python 代码中,你可以输入 “defs” 然后敲击 tab 键,你就能得到一段通用的函数定义。
同时,你还可以点击 Tools > New Snippet 来创建属于你自己的代码片。请参照这个 文档来获取帮助,也可以在 这里 查看我个人用到的一些 snippets。
自定义 Sublime Text 3
在你下载完 ST3 以后…
在命令行中添加 subl 命令
就像 TextMate 的 mate 命令一样,Sublime Text 拥有一个叫做 subl 的命令行工具,可以用来通过终端打开一个文件或者一整个文件夹。
你需要建立一个指向 subl 二进制文件的符号链接来使 subl 命令有效:

Python

1

$ ln -s "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" ~/bin/subl

尝试使用以下命令来打开 Sublime 来确保链接生效了:

Python

1

$ subl

如果以上命令没有效果,你可能需要将 /bin 添加到你的环境变量中:

Python

1

$ echo "export PATH=~/bin:$PATH" &gt;&gt; ~/.profile

然后重新尝试第一步。
如果你仍然遇到问题,尝试查看 这篇 文章来获取帮助。 或者你可以看看如何在 Windows和 Linux 中建立符号链接。
现在你就可以通过下述命令来打开文件或者文件夹了:

Python

1
2
3
4
5
6
7
8

# open the current directory
$ subl .

# open a directory called tests
$ subl ~/Documents/test

# open a file called text.txt
$ subl test.txt

如果路径中含有空格,你必须使用双引号将路径括起来:

Python

1

$ subl "~/Documents/test/my test file.txt"

想要查询所有可用的命令,请打开帮助文件:

Python

1

$ subl --help

安装 Package Control
为了使用众多的 插件 来扩展 Sublime 的功能,你需要安装一个叫做 Package Control 的插件管理器——这个东西你必须要手动安装。但是一旦你安装好了以后,你就可以使用 Package Control 来安装,移除或者升级所有的 ST3 插件了。
点击 这里 从 Sublime Text 3 官方获取用于安装的代码。依次点击 View > Show Console 打开 ST3 的控制台。在控制台中粘贴刚才的代码,然后点击回车。最后重启 ST3。
现在你可以通过快捷键 cmd+shift+P 打开 Package Control 来安装其他的插件了。输入 install 然后你就能看见屏幕上出现了 Package Control: Install Package,点击回车然后搜索你想要的插件。
其他一些相关命令如下:
List Packages 显示所有已安装的插件
Remove Packages 移除一个指定的插件
Upgrade Package 更新一个指定的插件
Upgrade/Overwrite All Packages 更新所有已安装的插件
请查阅官方 文档 获取更多的命令。

创建自定义配置文件
你可以通过一个基于 JSON 的配置文件来充分的自定义 Sublime Text,这使得转移或者同步你的自定义文件到另一个系统变得非常容易。首先,我们需要新建我们自己的配置文件。我们最好是为不同的系统环境和编程语言各自创建一个配置文件。
依次点击 Sublime Text > Preferences > Settings – User 来创建一个配置文件。在该文件中添加一个空的 JSON 类然后就可以在其中写入你的配置内容了。如下所示:

Python

1
2
3
4
5
6
7

{
// base settings
"auto_complete": false,
"sublimelinter": false,
"tab_size": 2,
"word_wrap": true
}

如果想为特定的编程语言新建配置文件的话,请点击 Sublime Text > Preferences > Settings – More > Syntax Specific – User。然后按照 LANGUAGE.sublime-settings 的格式保存该配置文件。例如想新建一个 Python 专用的配置文件,请将该文件保存为 Python.sublime-settings。
你完全可以按照你自己的喜好来进行各项配置;不过我强烈推荐以我的这份 配置文件 以及 Python 配置 作为基础,然后修改成你所需要的内容。
一个可选项: 你可以使用 Dropbox 来同步你的所有配置。你只需要将你的配置文件上传到 Dropbox 然后就可以将你的配置同步到你的任意一台设备上了。
你可以在 Sublime Text Unofficial Documentation 找到一些非常好的参考配置。
主题
ST3 为你提供了完全自定义化一个适合自己主题的能力。当然,你如果不是那么的挑剔的话,你可以通过 Package Control 从许许多多的由 Sublime 社区设计的 主题 中下载一个。 在下载之前你可以通过 ColorSublime 来预览这些主题。
广受欢迎的的 Soda Dark 和极简风格的 Flatland 是我个人最喜欢的两个主题。
在安装完了主题以后, 请务必更新你的配置文件. Sublime Text > Preferences > Settings – User:

Python

1
2
3
4

{
"theme": "Flatland Dark.sublime-theme",
"color_scheme": "Packages/Theme - Flatland/Flatland Dark.tmTheme"
}

插件
除了那些主题以外,我还会使用以下这一些插件来提升我的工作效率。
SideBarEnhancements
SideBarEnhancements 扩展了侧边栏中菜单选项的数量,从而提升你的工作效率。诸如”New file” 和 “Duplicate” 这样的选项对于 ST3 来说实在是太重要了, 我甚至觉得 ST3 本来就应该提供这些功能。而且仅凭 “Delete” 这一个功能就让这个插件值得下载。这个功能将你会在你删除文件的时候把它放入回收站。虽然这个功能乍一看没什么用,但是当你没有使用这样的功能而彻底删除了一个文件的时候,除非你用了版本管理软件,否则你将很难恢复这个文件。

现在就下载吧!
Anaconda
Anaconda 是一个终极 Python 插件。它为 ST3 增添了多项 IDE 类似的功能,例如:
Autocompletion 自动完成,该选项默认开启,同时提供多种配置选项。
Code linting 使用支持 pep8 标准的 PyLint 或者 PyFlakes。因为我个人使用的是另外的 linting 工具,所以我会在 Anaconda 的配置文件 Anaconda.sublime-settings中将 linting 完全禁用。操作如下: Sublime > Preferences > Package Settings > Anaconda > Settings – User: {"anaconda_linting": false}
McCabe code complexity checker 让你可以在特定的文件中使用 McCabe complexity checker. 如果你对软件复杂度检查工具不太熟悉的话,请务必先浏览上边的链接。
Goto Definitions 能够在你的整个工程中查找并且显示任意一个变量,函数,或者类的定义。
Find Usage 能够快速的查找某个变量,函数或者类在某个特定文件中的什么地方被使用了。
Show Documentation: 能够显示一个函数或者类的说明性字符串(当然,是在定义了字符串的情况下)

你可以在这里,或者通过 ST3 的 Package Settings: Sublime Text > Preferences > Package Settings > Anaconda > README 来查看所有这些特性。
SublimeCodeIntel 是另外一个非常流行的插件,它的许多特性与 Anaconda 类似。我建议同时也试试它。
Djaneiro
Djaneiro 支持 Django 模版和关键字高亮以及许多实用的代码片(snippets)功能。其中的 snippets 绝对是省时神器。你可以通过很少几个关键字就能创建许多常见的 Django 代码块比如 templates,models,forms,以及 views。请查看官方文档获取 snippets 列表。
我个人非常喜欢的以下两个用于创建 template 的代码片:输入 var 就可以新建 {{ }},而输入 tag 就能新建 {% %}。
requirementstxt
Requirementstxt 可以为你的 requirements.txt 文件提供自动补全,语法高亮以及版本管理功能。
SublimeLinter
SublimeLinter 是 ST3 的一个代码静态检查工具框架(linter)。这个插件本身来说并不包含任何的一个 linter,但是你可以通过在 Package Control 中输入 SublimeLinter-[linter_name] 的方式来安装一个 linter。你可以点击这里查看官方的 linter。同时你还可以在 Package Control 中查看到许多的第三方 linter。请点击这里查看安装说明。
对于 Python 的代码静态检查器,我建议使用 SublimeLinter-pyflakes 和 SublimeLinter-pep8。
与此同时,我也会使用 SublimeLinter-jshint, SublimeLinter-pyyaml, SublimeLinter-csslint,SublimeLinter-html-tidy,以及 SublimeLinter-json。
以上大多数的 linter 都需要先安装一些依赖库才能使用,所以在安装前请务必阅读他们的安装说明。
你可以通过修改用户自定义的 SublimeLinter.sublime-settings 文件来对你的每个 linter 个性化:Sublime Text > Preferences > Package Settings > SublimeLinter > Settings – User. 例如我通过以下代码来忽略 pep8 中的错误和警告:

Python

1
2
3
4
5
6
7
8

"pep8": {
"@disable": false,
"args": [],
"excludes": [],
"ignore": "E501,C0301,W0142,W0402,R0201,E1101,E1102,C0103,R0901,R0903,R0904,C1001,W0223,W0232,W0201,E1103,R0801,C0111",
"max-line-length": 100,
"select": ""
},

GitGutter
GitGutter 让 ST3 能在左边栏的位置显示一个小图标,用以表示在最后一次提交以后,代码是否有追加,修改或者删除。

如果你想让该插件支持分布式的版本管理软件(Git,SVN,Bazaar 和 Mercurial)。请查看 Modific。
FTPSync
FTPSync 能够将你的项目和远程文件进行同步。你只需要打开文件便可以下载更新(如果你的远端文件比本地更加新的话),而且如果你对本地文件做出了修改可以立即同步到远程服务器。这是非常棒的同步本地文件和远程文件的方法。你可以通过以下的方法来添加你的远程服务器:Sublime Text > Preferences > Package Settings > FTPSync > Setup FTPSync.
Sample settings:

Python

1
2
3
4
5
6
7
8
9
10
11

{
'primary': {
host: 'ftp.mywebsite.com',
username: 'johnsmith',
password: 'secretpassword',
path: '/www/',

upload_on_save: true,
tls: true
}
}

我个人喜欢把密码设为 null 因为我不想让我的密码出现在配置文件中。这样 FTPSync 会在我每次保存完文件后要求我输入密码。
AdvancedNewFile
AdvancedNewFile 可以让你在 ST3 中使用简单的几个快捷键便创建一个新的文件夹或者一个新的文件:
你只需要通过几个快捷键便可以打开 AdvancedNewFile 的输入框。然后输入路径和文件名。当你按下回车键后,文件便被创建了。除此之外,如果目标文件夹并不存在的话,该文件夹将会被自动建立。在默认情况下,你创建的文件的路径将会显示在状态栏中。
请查看 Github 上的这篇文档来获取更为详细的使用说明。特别建议请详细阅读TAB自动补全(Tab Completion)以及预定义别名(Predefined Aliases)部分。
我把“cmd+n”设置为了通过 AdvancedNewFile 创建新文件的快捷方式。该快捷键可以通过修改 Key Bindings – User file 来实现 Sublime Text > Preferences > Package Settings > AdvancedNewFile > Key Bindings – User:

Python

1
2
3

[
{ "keys": ["cmd+n"], "command": "advanced_new_file_new"}
]

你也可以更改默认打开的文件夹路径:Sublime Text > Preferences > Package Settings > AdvancedNewFile > Settings – User

Python

1

{"default_initial": "/Users/michaelherman/Documents/repos"}

这样我创建新文件的时候,/Users/michaelherman/Documents/repos将会自动被添加到路径最前方,因为99%的情况下我都会把我的脚本放在这个路径下。
Emmet
Emmet,以前叫做 Zen Coding,让你可以通过简单的缩写来创建 HTML 或者 CSS 的代码块。
例如,你只需要输入感叹号!,然后按下 tab 键,便可以在一个 HTML 文件中创建一段带有几个基本标签的 HTML5 文档类型的代码:

Python

1
2
3
4
5
6
7
8
9
10

&lt;!doctype html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;/body&gt;
&lt;/html&gt;

请查看官方文档或者速查手册获取更多信息。
Markdown Preview
Markdown Preview 可以用来预览和编译 markdown 文件。
你可以打开 Package Manager 然后输入 Markdown Preview 来查看可用的命令:
Markdown Preview: Python Mrakdown: 在浏览器中预览
Markdown Preview: Python Mrakdown: 导出 HTML 文件
Markdown Preview: Python Mrakdown: 拷贝到剪贴板
Markdown Preview: Github风格Markdown: 在浏览器中预览
Markdown Preview: Github风格Markdown: 导出 HTML 文件
Markdown Preview: Github风格Markdown: 拷贝到剪贴板
Markdown Preview: 打开Markdown速查手册
一旦你完成转换,你之后的所有保存都会立即反映到转换的文件中。
快捷键
跳转到任意内容 (“cmd+p”) 用来快速查找和打开文件。你仅仅只需要工程中文件的一部分路径或者文件名你就可以很容易的打开这个文件。这在一个大型的 Django 工程中显得非常方便。
跳转到指定行 (“ctrl+g”) 让你在当前文件中跳转到指定行数。
跳转到标志 (“cmd+r”) 可以列出当前文件中所有的函数或者类,让你更方便查找。你可以通过输入关键字来查找你所需要的函数或者类。
跳转到行首 (cmd+left-arrow-key) 与 跳转到行尾 (cmd+right-arrow-key)
删除当前行(ctrl+shift+k)
多重编辑 是我迄今为止最喜欢的快捷键

Python

1
2

1.选定一个单词,点击 **“cmd+d”** 来选择同样的单词,再次点击 **“cmd+d”** 继续选择下一个单词…
2.或者 **“cmd+单击”** 来指定多个你想要同时修改的地方。

块编辑 (option+left-mouse-click) 用于选择一整块的内容。通常在整理 CSV 文件的时候用于删除空白内容。
如果想了解更多关于快捷键的内容,请看一下这篇文章。
自定义命令
你可以很容易地使用 Python 来编辑你自己的自定义命令和快捷键组合。目前我个人使用的有以下这些:
拷贝当前文件路径到剪贴板 – 链接
关闭除当前活动标签页以外的所有其他标签页 – 链接
通过文件选项打开你的 Package 文件夹(Sublime > Preferences > Browse Packages),然后打开 User 文件夹,接下来将上述的 Python 文件添加到 “/Sublime Text 3/Packages/User” 文件夹中。最后请在 Key Bindings – User file (Sublime Text > Preferences > Package Settings > AdvancedNewFile > Key Bindings – User) 文件中完成快捷键绑定。

Python

1
2
3
4
5
6
7
8
9
10
11
12

[
// Copy file name
{
"keys": ["cmd+shift+c"],
"command": "_path_to_clipboard"
},
// Close all other tabs
{
"keys": ["cmd+alt+w"],
"command": "close_tabs"
}
]

I. 如何利用python在pycharm上进行语音合成

pycharm 通过 SFTP 远程编辑项目的配置

{这个相当于代码同步,类似git上传,同步后你可以在服务器上直接运行上传的代码;这个配置好后,才能在pycharm远程调试时候将代码上传到服务器正确位置/正确路径上}

打开pycharm,File -> Settings…( Ctrl + Alt + s ) -> Deployment
点击 + 按钮,添加一个

如果你发现你的运行配置中没有 Django 相关的项,请在项目设置的 Django 中勾选 Enable Django Support。

运行配置的设置有两点需要注意。Python Interpreter 需要选中之前建立的远程解释器。Path mappings 处,需要把本机的 manage.py 与 Linux 上的关联起来,比如:

C:/Evolution/Python/django_website/manage.py <=> /home/onlyice/work/django_website/manage.py

这可能是 PyCharm 的 bug:在使用远程解释器后,PyCharm 并不会自动将 Django 运行配置中的 manage.py 文件定位到 Linux 上的那份,而是会尝试使用下面的命令来启动 Django 调试 Server:

/usr/bin/python2 manage.py C:/Evolution/Python/django_website/manage.py

自然就找不到文件了。所以使用了 Path mappings 作为一种 hack 手段来解决。
这时就可以打断点调试啦

Trouble Shooting

Q: 点击调试运行失败,显示 “Cant set remote tunneling”

A: 调试时 PyCharm 调用将 Python Debug Server (pydevd.py) 绑定在一个随机端口上,再使用 SSH 的端口转发将数据通过 SSH 端口转到 Debug Server 去。需要检查你的 sshd 配置 (默认是 /etc/ssh/sshd_config) 是否禁用了 TCP 转发 (AllowTcpFowarding),这个配置默认是打开的。

皮皮blog

出错问题

pycharm channel is not opened

pycharm不能同步deployment中设置的文件内容了,在remote host窗口中打开文件提示the file is identical to local但实际上完全不同,上传多次才能成功,或者干脆就提示channel is not opened。应该和sftp有关。

目前还没找到具体原因,可能是服务器问题,过会就自己好了。

也可能是pycharm的问题,或者系统的问题?希望解决的可以留言告知一下,谢谢!

[Can't Download From Remote Server via SFTP – JetBrains IntelliJ]

pandas出错

pycharm console import pandas Backend Qt4Agg is interactive backend. Turning interactive mode on. : cannot connect to X server
import pandas : cannot connect to X server

重启pycharm,或者也不知道怎么了就好了,不报错了。。。

运行出错

ssh://[email protected]:22/home/piting/ENV/anaconda3/bin/python3 -u /home/piting/mine/python_workspace/Oth/Competition/TianChi/Regression.py
/home/piting/ENV/anaconda3/bin/python3: can't open file '/home/piting/mine/python_workspace/Oth/Competition/TianChi/Regression.py': [Errno 2] No such file or directory

点出remote host标签,发现没有这个目录,目录下也没有这个文件

解决:

mkdir -p 代码目录

再在remote host中右键 》 upload here

ref: [PyCharmRemote Debugging指南]

[pycharm奇淫技巧]*

[使用Pycharm进行Python远程开发]

[Deployment in PyCharm]

J. 为啥我的Python这么慢

Pythn是动态类型而不是静态类型的,这意味着,在程序执行时,解释器并不知道变量的类型。对C语言来说,编译器在声明变量的时候就知道其类型了;对Python来说,程序执行时只知道一个变量是某种Python对象。
对于下面的C代码
int a = 1;

int b = 2;
int c = a + b;
编译器始终知道a和b是整型,在执行相加运算时,流程如下:
把<int> 1赋值给a

把<int> 2赋值给b
调用binary_add<int, int>(a, b)
把结果赋值给c
实现同样功能的Python代码如下
a = 1

b = 2
c = a + b
解释器只知道1和2是对象,但是并不知道这个对象的类型。所以解释器必须检查每个变量的PyObject_HEAD才能知道变量类型,然后执行对应的相加操作,最后要创建一个新的Python对象来保存返回值,大致流程如下:
把1赋值给a

设置a->PyObject_HEAD->typecode为整型

设置a->val = 1
把2赋值给b
设置a->PyObject_HEAD->typecode为整型

设置b->val = 2
调用binary_add<int, int>(a, b)
a->PyObject_HEAD获取类型编码

a是一个整型;值为a->val
b->PyObject_HEAD获取类型编码
b是一个整型,值为b->val
调用binary_add<int, int>(a->val, b->val)
结果为整型,存在result中
创建对象c
设c->PyObject_HEAD->typecode为整型

设置c->val为result
动态类型意味着任何操作都会涉及更多的步骤。这是Python对数值操作比C语言慢的主要原因
Python是解释型语言

上面介绍了解释型代码和编译型代码的一个区别。智能的编译器可以提前预见并优化重复或不需要的操作,这会带来性能的提升。编译器是一个大的话题,这里不会展开。

Python的对象模型会带来低效的内存访问

和C语言的整数对比时,我们指出了Python多了额外一层信息。现在来看看数组的情况。在Python中我们可以使用标准库中提供的List对象;而在C语言中我们会使用基于缓冲区的数组。

最简单的NumPy数组是围绕C数据构建的Python对象,也就是说它有一个指向连续数据缓存区的指针。而Python的list具有指向连续的指针缓冲区的指针,这些指针每个都指向一个Python对象,结合上面的例子,这些Python对象是一个整数对象。这个结构像下面这样

很容易看出,如果你正在执行按顺序逐步完成数据的操作,numpy的内存布局比Python的内存布局更为高效,无论是存储成本还是访问的时间成本。

为什么使用Python

鉴于Python天生的低效率,我们为什么还要使用Python呢?种种理由大致可以归结为:动态类型使得Python比C更容易使用。Python非常的灵活和宽容,这种灵活性可以有效地利用开发时间,并且在那些确实需要C和Fortran优化的场合,Python可以轻松链接到已编译的库中。这也是Python在科学社区的使用率不断增长的原因。经提到了一些结论性的东西,下面我们用Python的一些工具来做一些验证。

下面的实验使用到了python, ipython, numpy,版本信息如下:

python:3.6.5

1.13.3
In [1]: import sys
In [2]: import numpy
In [3]: sys.version[:5]
Out[3]: '3.6.5'
In [4]: numpy.__version__
Out[4]: '1.13.3'
本次实验使用机器64位的机器,如果是32位的机器话,下面提到的一些struct可能会有所不同。
整数
Python的整数使用起来非常简单。
In [5]: x = 42
In [6]: print(x)
42
接口的简单性掩盖了底层的复杂。在之前的内容里有提到过Python整数的内存布局。现在我们使用Python内置的ctypes模块来自省整数类型,前提是需要知道在C API中Python整数类型的定义。
在CPython中,变量x存储在一个名为_longobject的struct中,源码见Include/longintrepr.h
struct _longobject {
PyObject_VAR_HEAD
digit ob_digit[1];
}
其中PyObject_VAR_HEAD是一个宏,在Include/object.h中定义的结构如下
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size;
} PyVarObject;
其中PyObject在Include/object.h中定义如下
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
}
其中_PyObject_HEAD_EXTRA是一个在Python版本中通常不使用的宏。
将上面的信息结合起来,可以得到下面的结构
struct _longobject {
long ob_refcnt;
PyTypeObject *ob_type;
size_t ob_size;
long ob_digit[1];
}
这里面ob_refcnt变量是对象的引用计数,ob_type是指向包含该对象所有类型信息和方法定义的结构的指针,ob_digit保存实际的数值。
有了上面的知识,可以开始使用ctypes模块来观察时间的对象结构并提取上面的信息。
现在来用Python定义一个C的struct
In [7]: import ctypes
In [9]: class IntStruct(ctypes.Structure):
...: _fields_ = [
...: ("ob_refcnt", ctypes.c_long),
...: ("ob_type", ctypes.c_void_p),
...: ("ob_size", ctypes.c_ulong),
...: ("ob_digit", ctypes.c_long)
...: ]
...:
...: def __repr__(self):
...: return (
...: "IntStruct(ob_digit)={self.ob_digit}, refcount={self.ob_refcnt}"
...: ).format(self=self)
...:
现在用42来做实验。在Python中,id方法会返回对象的内存地址:
In [10]: num = 42
In [11]: IntStruct.from_address(id(42))
Out[11]: IntStruct(ob_digit)=42, refcount=61
可以看到ob_digit指向了内存中的正确位置。但是这里只创建了一个对象,为什么引用次数是61呢?
事实证明,这是一个性能优化,Python使用了很多小的整数,如果为每一个数字都创建一个PyObject,会消耗掉不少内存。出于这个考虑,Python将一些常用的数字做了单例实现,这样每个数字在内存中只有一份拷贝。换句话说,如果在这个范围内创建一个新的Python整数时,只是创建了一个对该数值对象的引用。
In [16]: x = 42
In [17]: y = 42
In [18]: id(x) == id(y)
Out[18]: True
上面的例子中,x和y都指向了同一个内存地址。在使用更大的数的时候,等式就不成立了
In [19]: x = 1234
In [20]: y = 1234
In [21]: id(x) == id(y)
Out[21]: False
Python解释器启动时候会创建很多的整数对象;可以看看这些对象的引用分布
%matplotlib osx
import matplotlib.pyplot as plt
import sys
plt.loglog(range(1000), [sys.getrefcount(i) for i in range(1000)])
plt.xlabel('integer value')
plt.ylabel('reference count')
Out[8]: Text(0,0.5,'reference count')
可以看到0被引用了数千次,一般情况下,引用的频率随着整数值的增加而减少。
再来看看ob_digit对应的值
In [8]: all(i == IntStruct.from_address(id(i)).ob_digit for i in range(256))
Out[8]: True
如果更细心一点,就可以发现,对于大于256的值,ob_digit就不能对应到正确的值了:在Objects/longobject.c中对数值有一些移位操作,这也是Python对一些大整数的处理方式。
比如
In [11]: 2 ** 100
Out[11]:
这个值显然是超过了long类型的范围了。
List类型
现在来看看一个更复杂的数据类型:List。同样能在Include/listobject.h中找到List类型的struct结构:
typedef struct {
PyObject_VAR_HEAD
PyObject **ob_item;
Py_ssize_t allocated;
} PyListObject;
和之前一样,得到有效的结构体如下:
typedef struct {
long ob_refcnt;
PyTypeObject *ob_type;
Py_ssize_t ob_size;
PyObject **ob_item;
long allocated;
} PyListObject;
其中PyObject **ob_item指向list的数据,ob_size指出list中数据的个数。
In [3]: class ListStruct(ctypes.Structure):
...: _fields_ = [("ob_refcnt", ctypes.c_long),
...: ("ob_type", ctypes.c_void_p),
...: ("ob_size", ctypes.c_ulong),
...: ("ob_item", ctypes.c_long), # PyObject** pointer cast t
...: o long
...: ("allocated", ctypes.c_ulong)]
...:
...: def __repr__(self):
...: return ("ListStruct(len={self.ob_size}, "
...: "refcount={self.ob_refcnt})").format(self=self)
试验一下
In [8]: L = [1, 2, 3, 4]
In [9]: ListStruct.from_address(id(L))
Out[9]: ListStruct(len=4, refcount=1)
为确保得到的结果是正确的,对这个list增加几个引用,看看会不会影响引用计数:
In [10]: tup = [L, L]
In [11]: ListStruct.from_address(id(L))
Out[11]: ListStruct(len=4, refcount=3)
使用ctypes可以创建由之前IntStruct对象组成的复合结构
In [20]: Lstruct = ListStruct.from_address(id(L))
In [21]: PtrArray = Lstruct.ob_size * ctypes.POINTER(IntStruct)
In [22]: L_values = PtrArray.from_address(Lstruct.ob_item)
看看每个元素的值
In [23]: [ptr[0] for ptr in L_values]
Out[23]:
[IntStruct(ob_digit=1, refcount=4705),
IntStruct(ob_digit=2, refcount=1102),
IntStruct(ob_digit=3, refcount=559),
IntStruct(ob_digit=4, refcount=726)]
NumPy的数组
同样的,我们来看看numpy中的数组。其C-API定义的结构见numpy/core/include/numpy/ndarraytypes.h,这里用的numpy版本是1.13.3,不同版本的结构可能有所不同。
In [25]: np.__version__
Out[25]: '1.13.3'
现在用ctypes来创建一个numpy数组的结构吧。
In [31]: class NumpyStruct(ctypes.Structure):
...: _fields_ = [("ob_refcnt", ctypes.c_long),
...: ("ob_type", ctypes.c_void_p),
...: ("ob_data", ctypes.c_long), # char* pointer cast to long
...: ("ob_ndim", ctypes.c_int),
...: ("ob_shape", ctypes.c_voidp),
...: ("ob_strides", ctypes.c_voidp)]
...:
...: @property
...: def shape(self):
...: return tuple((self.ob_ndim * ctypes.c_int64).from_address(self.ob_shape))
...:
...: @property
...: def strides(self):
...: return tuple((self.ob_ndim * ctypes.c_int64).from_address(self.ob_strides))
...:
...: def __repr__(self):
...: return ("NumpyStruct(shape={self.shape}, "
...: "refcount={self.ob_refcnt})").format(self=self)
新建一个numpy数组试试In [32]: x = np.random.random((10, 20)) In [33]: xstruct = NumpyStruct.from_address(id(x)) In [34]: xstruct Out[34]: NumpyStruct(shape=(10, 20), refcount=1)
可以看到已经拿到了正确的shape。现在看看引用计数的情况
In [35]: L = [x, x, x]
In [36]: xstruct
Out[36]: NumpyStruct(shape=(10, 20), refcount=4)
现在可以看看里面的数据了。
In [37]: x = np.arange(10)
In [38]: xstruct = NumpyStruct.from_address(id(x))
In [39]: size = np.prod(xstruct.shape)
In [40]: arraytype = size * ctypes.c_long
In [41]: data = arraytype.from_address(xstruct.ob_data)
In [42]: [d for d in data]
Out[42]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
上面的data变量存储了Numpy数组中定义的连续的内存块,可以改一下其中的值。
In [43]: x[4] = 555
In [44]: [d for d in data]
Out[44]: [0, 1, 2, 3, 555, 5, 6, 7, 8, 9]
上面的例子可以证明x和data指向了同一块连续内存。
比较Python的list和numpy的ndarray的内部结构,明显可以看出numpy的数据对于表示同类型的数据列表来说简单的多。
结语
Python很慢,正如上面所说,一个重要原因是类型的间接寻址,这也是Python对开发者友好的原因。同时,Python本身也提供了可用于破解Python对象的工具,通过使用这些工具可以解析CPython的一些内部行为。

阅读全文

与python静态代码检查工具相关的资料

热点内容
幻影服务器怎么样 浏览:25
具体哪些广东公司招程序员 浏览:867
嵌入式编译器教程 浏览:302
ssl数据加密传输 浏览:86
51单片机定时器方式2 浏览:330
命令行查看开机时间 浏览:812
python微博复杂网络分析 浏览:550
rf3148编程器 浏览:505
浙江标准网络服务器机柜云主机 浏览:587
设置网络的服务器地址 浏览:600
java图形界面设计 浏览:751
纯前端项目怎么部署到服务器 浏览:538
瓜子脸程序员 浏览:505
如何保证服务器优质 浏览:94
小微信aPP怎么一下找不到了 浏览:299
算法纂要学术价值 浏览:975
程序员你好是什么意思 浏览:802
倩女幽魂老服务器如何玩 浏览:563
电子钟单片机课程设计实验报告 浏览:1001
看加密频道 浏览:382