Centos下扩展PHP模块Imagick详解

being 发表了文章 • 0 个评论 • 475 次浏览 • 2016-12-20 20:39 • 来自相关话题

简介

imagick是一个PHP的扩展,它调用ImageMagick提供的API来进行图片的操作

ImageMagick是一套软件系列,主要用于图片的创建、编辑以及转换等,详细的解释见ImageMagick的官方网站http://www.imagemagick.org/  ,ImageMagick与GD的性能要高很多,如果是在处理大量的图片时更加能体现ImageMagick的性能。
 
通常安装安装php的imagick扩展模块有两种方法,一种是利用pcel安装imagick(适用于php verison 5.4 或者更高),第二种就是手动下载编译安装,下面依次介绍。

一、pcel安装imagick

1、首先安装ImageMagick# cd /usr/local/src/
# wget ftp://ftp.u-aizu.ac.jp/pub/graphics/image/ImageMagick/imagemagick.org/ImageMagick-6.8.7-0.tar.gz
# tar zxf ImageMagick-6.8.7-0.tar.gz
# cd ImageMagick-6.8.7-0
# ./configure -prefix=/usr/local/imagemagick
# make && make install官网地址:http://www.imagemagick.org/
 
2、安装imagick# 首先进入到PHP的bin目录
# cd /usr/local/php5.6.26/bin/
# ./pecl install imagick

................
Build process completed successfully
Installing '/usr/local/php5.6.26/lib/php/extensions/no-debug-non-zts-20131226/imagick.so'
Installing '/usr/local/php5.6.26/include/php/ext/imagick/php_imagick_shared.h'
install ok: channel://pecl.php.net/imagick-3.4.3RC1
configuration option "php_ini" is not set to php.ini location
You should add "extension=imagick.so" to php.ini产生的imagick.so文件拷贝到/usr/local/php5.6.26/lib/php/extensions/no-debug-non-zts-20131226下
 
在php.ini文件里添加imagick.so,然后重启php加载imagick模块即可,使用/usr/local/php5.6.26/bin/php -m 命令查看模块是否添加成功。

二、编译安装imagick

1、首先安装ImageMagick 同上
 
2、编译安装imagick# wget http://pecl.php.net/get/imagick-3.1.2.tgz
# tar zxf imagick-3.1.2.tgz
# cd imagick-3.1.2
# /usr/local/php5.3.6/bin/phpize (这个看你php安装路径)
# 注:phpize是一个shell脚本,主要是用来进行编译环境的准备,执行以后会生成一些新的文件,为配置、编译及安装作好准备
# ./configure --with-php-config=/usr/local/php5.3.6/bin/php-config --with-imagick=/usr/local/imagemagick
# make && make install在php配置文件php.ini中添加:extension=imagick.so重启apache或php-fpm就可以了。 查看全部
PHP.png


简介


imagick是一个PHP的扩展,它调用ImageMagick提供的API来进行图片的操作

ImageMagick是一套软件系列,主要用于图片的创建、编辑以及转换等,详细的解释见ImageMagick的官方网站http://www.imagemagick.org/  ,ImageMagick与GD的性能要高很多,如果是在处理大量的图片时更加能体现ImageMagick的性能。
 
通常安装安装php的imagick扩展模块有两种方法,一种是利用pcel安装imagick(适用于php verison 5.4 或者更高),第二种就是手动下载编译安装,下面依次介绍。


一、pcel安装imagick


1、首先安装ImageMagick
# cd /usr/local/src/
# wget ftp://ftp.u-aizu.ac.jp/pub/graphics/image/ImageMagick/imagemagick.org/ImageMagick-6.8.7-0.tar.gz
# tar zxf ImageMagick-6.8.7-0.tar.gz
# cd ImageMagick-6.8.7-0
# ./configure -prefix=/usr/local/imagemagick
# make && make install
官网地址:http://www.imagemagick.org/
 
2、安装imagick
# 首先进入到PHP的bin目录
# cd /usr/local/php5.6.26/bin/
# ./pecl install imagick

................
Build process completed successfully
Installing '/usr/local/php5.6.26/lib/php/extensions/no-debug-non-zts-20131226/imagick.so'
Installing '/usr/local/php5.6.26/include/php/ext/imagick/php_imagick_shared.h'
install ok: channel://pecl.php.net/imagick-3.4.3RC1
configuration option "php_ini" is not set to php.ini location
You should add "extension=imagick.so" to php.ini
产生的imagick.so文件拷贝到/usr/local/php5.6.26/lib/php/extensions/no-debug-non-zts-20131226下
 
在php.ini文件里添加imagick.so,然后重启php加载imagick模块即可,使用/usr/local/php5.6.26/bin/php -m 命令查看模块是否添加成功。


二、编译安装imagick


1、首先安装ImageMagick 同上
 
2、编译安装imagick
# wget http://pecl.php.net/get/imagick-3.1.2.tgz
# tar zxf imagick-3.1.2.tgz
# cd imagick-3.1.2
# /usr/local/php5.3.6/bin/phpize (这个看你php安装路径)
# 注:phpize是一个shell脚本,主要是用来进行编译环境的准备,执行以后会生成一些新的文件,为配置、编译及安装作好准备
# ./configure --with-php-config=/usr/local/php5.3.6/bin/php-config --with-imagick=/usr/local/imagemagick
# make && make install
在php配置文件php.ini中添加:
extension=imagick.so
重启apache或php-fpm就可以了。

Python最差实践变更

chris 发表了文章 • 0 个评论 • 333 次浏览 • 2016-12-20 17:28 • 来自相关话题

最近在看一些陈年老系统,其中有一些不好的代码习惯遗留下来的坑;加上最近自己也写了一段烂代码导致服务器负载飙升,所以就趁此机会总结下我看到过/写过的自认为不好的Python代码习惯,时刻提醒自己远离这些“最差实践”,避免挖坑。

下面所举的例子中,有一部分会造成性能问题,有一部分会导致隐藏bug,或日后维护、重构困难,还有一部分纯粹是我认为不够pythonic。所以大家自行甄别,取精去糟吧。
 

函数默认参数使用可变对象​

这个例子我想大家应该在各种技术文章中见过许多遍了,也足以证明这是一个大坑。
 
先看错误示范吧:
def use_mutable_default_param(idx=0, ids=[]):
ids.append(idx)
print(idx)
print(ids)

use_mutable_default_param(idx=1)
use_mutable_default_param(idx=2)输出:
1
[1]
2
[1, 2]理解这其中的原因,最重要的是有两点:
函数本身也是一个对象,默认参数绑定于这个函数对象上append这类方法会直接修改对象,所以下次调用此函数时,其绑定的默认参数已经不再是空list了
 
正确的做法如下:
def donot_use_mutable_default_param(idx=0, ids=None):
if ids is None:
ids = []
ids.append(idx)
print(idx)
print(ids)

try…except不具体指明异常类型

虽然在Python中使用try…except不会带来严重的性能问题,但是不加区分,直接捕获所有类型异常的做法,往往会掩盖掉其他的bug,造成难以追查的bug。

一般的,我觉得应该尽量少的使用try…except,这样可以在开发期尽早的发现问题。即使要使用try…except,也应该尽可能的指定出要捕获的具体异常,并在except语句中将异常信息记入log,或者处理完之后,再直接raise出来。
 

关于dict的冗余代码

我经常能够看到这样的代码:
d = {}
datas = [1, 2, 3, 4, 2, 3, 4, 1, 5]
for k in datas:
if k not in d:
d[k] = 0
d[k] += 1其实,完全可以使用collections.defaultdict这一数据结构更简单优雅的实现这样的功能:
default_d = defaultdict(lambda: 0)
datas = [1, 2, 3, 4, 2, 3, 4, 1, 5]
for k in datas:
default_d[k] += 1 同样的,这样的代码:
# d is a dict
if 'list' not in d:
d['list'] = []
d['list'].append(x)完全可以用这样一行代码替代:
# d is a dict
d.setdefault('list', []).append(x)同样的,下面这两种写法一看就是带有浓浓的C味儿:
# d is a dict
for k in d:
v = d[k]
# do something

# l is a list
for i in len(l):
v = l[i]
# do something应该用更pythonic的写法:
# d is a dict
for k, v in d.iteritems():
# do something
pass

# l is a list
for i, v in enumerate(l):
# do something
pass另外,enumerate其实还有个第二参数,表示序号从几开始。如果想要序号从1开始数起,可以使用enumerate(l, 1)。 
 

使用flag变量而不使用for…else语句

同样,这样的代码也很常见:
search_list = ['Jone', 'Aric', 'Luise', 'Frank', 'Wey']
found = False
for s in search_list:
if s.startswith('C'):
found = True
# do something when found
print('Found')
break

if not found:
# do something when not found
print('Not found') 其实,用for…else更优雅:
search_list = ['Jone', 'Aric', 'Luise', 'Frank', 'Wey']
for s in search_list:
if s.startswith('C'):
# do something when found
print('Found')
break
else:
# do something when not found
print('Not found')

 

过度使用tuple unpacking

在Python中,允许对tuple类型进行unpack操作,如下所示:
# human = ('James', 180, 32)
name,height,age = human这个特性用起来很爽,比写name=human[0]之类的不知道高到哪里去了。所以,这一特性往往被滥用,一个human在程序的各处通过上面的方式unpack。

然而如果后来需要在human中插入一个表示性别的数据sex,那么对于所有的这种unpack都需要进行修改,即使在有些逻辑中并不会使用到性别。
# human = ('James', 180, 32)
name,height,age, _ = human
# or
# name, height, age, sex = human有如下几种方式解决这一问题:
老老实实写name=human[0]这种代码,在需要使用性别信息处加上sex=human[3]使用dict来表示human使用namedtuple
 
# human = namedtuple('human', ['name', 'height', 'age', 'sex'])
h = human('James', 180, 32, 0)
# then you can use h.name, h.sex and so on everywhere.

到处都是import *

import *是一种懒惰的行为,它不仅会污染当前的命名空间,并且还会使得pyflakes等代码检查工具失效。在后续查看代码或者debug的过程中,往往也很难从一堆import *中找到一个第三方函数的来源。

可以说这种习惯是百害而无一利的。
 

文件操作

文件操作不要使用裸奔的f = open(‘filename’)了,使用with open(‘filename’) as f来让context manager帮你处理异常情况下的关闭文件等乱七八糟的事情多好。
 

野蛮使用class.name判断类型

我曾经遇见过一个bug:为了实现某特定功能,我新写了一个class B(A),在B中重写了A的若干函数。整个实现很简单,但是就是有一部分A的功能无法生效。最后追查到的原因,就是在一些逻辑代码中,硬性的判断了entity.__class__.__name__ == ‘A’。

除非你就是想限定死继承层级中的当前类型(也就是,屏蔽未来可能会出现的子类),否则,不要使用__class__.__name__,而改用isinstance这个内建函数。毕竟,Python把这两个变量的名字都刻意带上那么多下划线,本来就是不太想让你用嘛。
 

循环内部有多层函数调用

循环内部有多层函数调用,有如下两方面的隐患:
Python没有inline函数,所以函数调用本来就会导致一定的开销,尤其是本身逻辑简单的时候,这个开销所占的比例就会挺可观的。更严重的是,在之后维护这份代码时,会容易让人忽略掉函数是在循环中被调用的,所以容易在函数内部添加了一些开销较大却不必每次循环都调用的函数,比如time.localtime()。如果是直接一个平铺直叙的循环,我想大部分的程序员都应该知道把time.localtime()写到循环的外面,但是引入多层的函数调用之后,就不一定了哦。
 
所以我建议,在循环内部,如非特别复杂的逻辑,都应该直接写在循环里,不要进行函数调用。如果一定要包装一层函数调用,应该在函数的命名或注释中,提示后续的维护者,这个函数会在循环内部使用。
 

总结

Python是一门非常容易入门的语言,严格的缩进要求和丰富的内置数据类型,使得大部分Python代码都能做到比较好的规范。但是,不严格要求自己,也很容易就写出犯二的代码。上面列出的只是很小的一部分,唯有多读、多写、多想,才能培养敏锐的代码嗅觉,第一时间发现坏味道啊。
 

分享阅读:http://blog.guoyb.com/2016/12/03/bad-py-style/
作者:yubo 查看全部
python.png
最近在看一些陈年老系统,其中有一些不好的代码习惯遗留下来的坑;加上最近自己也写了一段烂代码导致服务器负载飙升,所以就趁此机会总结下我看到过/写过的自认为不好的Python代码习惯,时刻提醒自己远离这些“最差实践”,避免挖坑。

下面所举的例子中,有一部分会造成性能问题,有一部分会导致隐藏bug,或日后维护、重构困难,还有一部分纯粹是我认为不够pythonic。所以大家自行甄别,取精去糟吧。
 


函数默认参数使用可变对象​


这个例子我想大家应该在各种技术文章中见过许多遍了,也足以证明这是一个大坑。
 
先看错误示范吧:
def use_mutable_default_param(idx=0, ids=[]):
ids.append(idx)
print(idx)
print(ids)

use_mutable_default_param(idx=1)
use_mutable_default_param(idx=2)
输出:
1
[1]
2
[1, 2]
理解这其中的原因,最重要的是有两点:
  1. 函数本身也是一个对象,默认参数绑定于这个函数对象上
  2. append这类方法会直接修改对象,所以下次调用此函数时,其绑定的默认参数已经不再是空list了

 
正确的做法如下:
def donot_use_mutable_default_param(idx=0, ids=None):
if ids is None:
ids = []
ids.append(idx)
print(idx)
print(ids)


try…except不具体指明异常类型


虽然在Python中使用try…except不会带来严重的性能问题,但是不加区分,直接捕获所有类型异常的做法,往往会掩盖掉其他的bug,造成难以追查的bug。

一般的,我觉得应该尽量少的使用try…except,这样可以在开发期尽早的发现问题。即使要使用try…except,也应该尽可能的指定出要捕获的具体异常,并在except语句中将异常信息记入log,或者处理完之后,再直接raise出来。
 


关于dict的冗余代码


我经常能够看到这样的代码:
d = {}
datas = [1, 2, 3, 4, 2, 3, 4, 1, 5]
for k in datas:
if k not in d:
d[k] = 0
d[k] += 1
其实,完全可以使用collections.defaultdict这一数据结构更简单优雅的实现这样的功能:
default_d = defaultdict(lambda: 0)
datas = [1, 2, 3, 4, 2, 3, 4, 1, 5]
for k in datas:
default_d[k] += 1
同样的,这样的代码:
# d is a dict
if 'list' not in d:
d['list'] = []
d['list'].append(x)
完全可以用这样一行代码替代:
# d is a dict
d.setdefault('list', []).append(x)
同样的,下面这两种写法一看就是带有浓浓的C味儿:
# d is a dict
for k in d:
v = d[k]
# do something

# l is a list
for i in len(l):
v = l[i]
# do something
应该用更pythonic的写法:
# d is a dict
for k, v in d.iteritems():
# do something
pass

# l is a list
for i, v in enumerate(l):
# do something
pass
另外,enumerate其实还有个第二参数,表示序号从几开始。如果想要序号从1开始数起,可以使用enumerate(l, 1)。 
 


使用flag变量而不使用for…else语句


同样,这样的代码也很常见:
search_list = ['Jone', 'Aric', 'Luise', 'Frank', 'Wey']
found = False
for s in search_list:
if s.startswith('C'):
found = True
# do something when found
print('Found')
break

if not found:
# do something when not found
print('Not found')
其实,用for…else更优雅:
search_list = ['Jone', 'Aric', 'Luise', 'Frank', 'Wey']
for s in search_list:
if s.startswith('C'):
# do something when found
print('Found')
break
else:
# do something when not found
print('Not found')

 


过度使用tuple unpacking


在Python中,允许对tuple类型进行unpack操作,如下所示:
# human = ('James', 180, 32)
name,height,age = human
这个特性用起来很爽,比写name=human[0]之类的不知道高到哪里去了。所以,这一特性往往被滥用,一个human在程序的各处通过上面的方式unpack。

然而如果后来需要在human中插入一个表示性别的数据sex,那么对于所有的这种unpack都需要进行修改,即使在有些逻辑中并不会使用到性别。
# human = ('James', 180, 32)
name,height,age, _ = human
# or
# name, height, age, sex = human
有如下几种方式解决这一问题:
  1. 老老实实写name=human[0]这种代码,在需要使用性别信息处加上sex=human[3]
  2. 使用dict来表示human
  3. 使用namedtuple

 
# human = namedtuple('human', ['name', 'height', 'age', 'sex'])
h = human('James', 180, 32, 0)
# then you can use h.name, h.sex and so on everywhere.


到处都是import *


import *是一种懒惰的行为,它不仅会污染当前的命名空间,并且还会使得pyflakes等代码检查工具失效。在后续查看代码或者debug的过程中,往往也很难从一堆import *中找到一个第三方函数的来源。

可以说这种习惯是百害而无一利的。
 


文件操作


文件操作不要使用裸奔的f = open(‘filename’)了,使用with open(‘filename’) as f来让context manager帮你处理异常情况下的关闭文件等乱七八糟的事情多好。
 


野蛮使用class.name判断类型


我曾经遇见过一个bug:为了实现某特定功能,我新写了一个class B(A),在B中重写了A的若干函数。整个实现很简单,但是就是有一部分A的功能无法生效。最后追查到的原因,就是在一些逻辑代码中,硬性的判断了entity.__class__.__name__ == ‘A’。

除非你就是想限定死继承层级中的当前类型(也就是,屏蔽未来可能会出现的子类),否则,不要使用__class__.__name__,而改用isinstance这个内建函数。毕竟,Python把这两个变量的名字都刻意带上那么多下划线,本来就是不太想让你用嘛。
 


循环内部有多层函数调用


循环内部有多层函数调用,有如下两方面的隐患:
  1. Python没有inline函数,所以函数调用本来就会导致一定的开销,尤其是本身逻辑简单的时候,这个开销所占的比例就会挺可观的。
  2. 更严重的是,在之后维护这份代码时,会容易让人忽略掉函数是在循环中被调用的,所以容易在函数内部添加了一些开销较大却不必每次循环都调用的函数,比如time.localtime()。如果是直接一个平铺直叙的循环,我想大部分的程序员都应该知道把time.localtime()写到循环的外面,但是引入多层的函数调用之后,就不一定了哦。

 
所以我建议,在循环内部,如非特别复杂的逻辑,都应该直接写在循环里,不要进行函数调用。如果一定要包装一层函数调用,应该在函数的命名或注释中,提示后续的维护者,这个函数会在循环内部使用。
 


总结


Python是一门非常容易入门的语言,严格的缩进要求和丰富的内置数据类型,使得大部分Python代码都能做到比较好的规范。但是,不严格要求自己,也很容易就写出犯二的代码。上面列出的只是很小的一部分,唯有多读、多写、多想,才能培养敏锐的代码嗅觉,第一时间发现坏味道啊。
 


分享阅读:http://blog.guoyb.com/2016/12/03/bad-py-style/
作者:yubo


Python 备份Mysql

Not see︶ 发表了文章 • 0 个评论 • 647 次浏览 • 2016-09-23 19:26 • 来自相关话题

#!/usr/bin/env python
# Filename: mysql_backup.py
# author:kevin yang
# email:zhiwen.yang@showself.com
# date:2016-09-23
import os
import time
import sys
import datetime
from stat import *

# mysql user
User = 'root'

# mysql password
Passwd = '123456'

# mysqldump command
Mysqlcommand = 'mysqldump'

# gzip command
Gzipcommand = '/bin/gzip'

# you want backup mysql database
Mysqldata = ['PHPCMS', 'TeamToy']

# you want backup to dir
Tobackup = '/data/mysql_bak/'

for DB in Mysqldata:
# backup file name
Backfile = Tobackup + DB + '-' + time.strftime('%Y-%m-%d') + '.sql'
# gzip file name
Gzfile = Backfile +'.gz'
if os.path.isfile(Gzfile):
print Gzfile + " is already backup"
else:
# backup command
Back_command = Mysqlcommand + ' -u' + User + ' -p' + Passwd + ' -P3306 ' + DB + ' > ' + Backfile
if os.system(Back_command)==0:
print 'Successful backup to', DB + ' to ' + Backfile
else:
print 'Backup FAILED'
# gzip command
Gzip_command = Gzipcommand + ' ' + Backfile
if os.system(Gzip_command)==0:
print 'Successful Gzip to',Gzfile
else:
print 'Gzip FAILED'

# Delete back file
# show file list
filelist=[]
filelist=os.listdir(Tobackup)
# delete Gzfile 5 days ago
for i in range(len(filelist)):
ft=time.gmtime(os.stat(Tobackup+filelist[i])[ST_MTIME])
ftl=time.strftime('%Y-%m-%d',ft)
year,month,day=ftl.split('-')
ftll=datetime.datetime(int(year),int(month),int(day))
localt=time.gmtime()
localtl=time.strftime('%Y-%m-%d',localt)
year,month,day=localtl.split('-')
localtll=datetime.datetime(int(year),int(month),int(day))
days=(localtll-ftll).days
if days >5:
try:
os.remove(Tobackup+filelist[i])
print 'delete is ok'
except:
log=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+" remove "+Tobackup+filelist[i]+" fail \n"
print log 查看全部
#!/usr/bin/env python
# Filename: mysql_backup.py
# author:kevin yang
# email:zhiwen.yang@showself.com
# date:2016-09-23
import os
import time
import sys
import datetime
from stat import *

# mysql user
User = 'root'

# mysql password
Passwd = '123456'

# mysqldump command
Mysqlcommand = 'mysqldump'

# gzip command
Gzipcommand = '/bin/gzip'

# you want backup mysql database
Mysqldata = ['PHPCMS', 'TeamToy']

# you want backup to dir
Tobackup = '/data/mysql_bak/'

for DB in Mysqldata:
# backup file name
Backfile = Tobackup + DB + '-' + time.strftime('%Y-%m-%d') + '.sql'
# gzip file name
Gzfile = Backfile +'.gz'
if os.path.isfile(Gzfile):
print Gzfile + " is already backup"
else:
# backup command
Back_command = Mysqlcommand + ' -u' + User + ' -p' + Passwd + ' -P3306 ' + DB + ' > ' + Backfile
if os.system(Back_command)==0:
print 'Successful backup to', DB + ' to ' + Backfile
else:
print 'Backup FAILED'
# gzip command
Gzip_command = Gzipcommand + ' ' + Backfile
if os.system(Gzip_command)==0:
print 'Successful Gzip to',Gzfile
else:
print 'Gzip FAILED'

# Delete back file
# show file list
filelist=[]
filelist=os.listdir(Tobackup)
# delete Gzfile 5 days ago
for i in range(len(filelist)):
ft=time.gmtime(os.stat(Tobackup+filelist[i])[ST_MTIME])
ftl=time.strftime('%Y-%m-%d',ft)
year,month,day=ftl.split('-')
ftll=datetime.datetime(int(year),int(month),int(day))
localt=time.gmtime()
localtl=time.strftime('%Y-%m-%d',localt)
year,month,day=localtl.split('-')
localtll=datetime.datetime(int(year),int(month),int(day))
days=(localtll-ftll).days
if days >5:
try:
os.remove(Tobackup+filelist[i])
print 'delete is ok'
except:
log=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+" remove "+Tobackup+filelist[i]+" fail \n"
print log

Python程序软件目录规范化

采菊篱下 发表了文章 • 0 个评论 • 655 次浏览 • 2016-09-21 15:18 • 来自相关话题

为什么要设计好目录结构?

"设计项目目录结构",就和"代码编码风格"一样,属于个人风格问题。对于这种风格上的规范,一直都存在两种态度:
一类同学认为,这种个人风格问题"无关紧要"。理由是能让程序work就好,风格问题根本不是问题;另一类同学认为,规范化能更好的控制程序结构,让程序具有更高的可读性。
 
我是比较偏向于后者的,因为我是前一类同学思想行为下的直接受害者。我曾经维护过一个非常不好读的项目,其实现的逻辑并不复杂,但是却耗费了我非常长的时间去理解它想表达的意思。从此我个人对于提高项目可读性、可维护性的要求就很高了。"项目目录结构"其实也是属于"可读性和可维护性"的范畴,我们设计一个层次清晰的目录结构,就是为了达到以下两点:
可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。
 
所以,保持一个层次清晰的目录结构是有必要的。更何况组织一个良好的工程目录,其实是一件很简单的事儿。
 

目录组织方式

关于如何组织一个较好的Python工程目录结构,已经有一些得到了共识的目录结构。在Stackoverflow关于这个问题 ,可以看到很多赞同对Python目录结构规范的情况。

假设你的项目名为foo, 我比较建议的最方便快捷目录结构这样就足够了:Foo/
|-- bin/
| |-- foo
|
|-- foo/
| |-- tests/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- docs/
| |-- conf.py
| |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README简要解释一下:
bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py。docs/: 存放一些文档。setup.py: 安装、部署、打包的脚本。requirements.txt: 存放软件依赖的外部Python包列表。README: 项目说明文件。
 
除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,ChangeLog.txt文件等,我没有列在这里,因为这些东西主要是项目开源的时候需要用到。如果你想写一个开源软件,目录该如何组织,可以参考开源Python项目的正确方法 。

关于README的内容 

这个我觉得是每个项目都应该有的一个文件,目的是能简要描述该项目的信息,让读者快速了解这个项目。
 
它需要说明以下几个事项:
软件定位,软件的基本功能。运行代码的方法: 安装环境、启动命令等。简要的使用说明。代码目录结构说明,更详细点可以说明软件的基本原理。常见问题说明。
我觉得有以上几点是比较好的一个README。在软件开发初期,由于开发过程中以上内容可能不明确或者发生变化,并不是一定要在一开始就将所有信息都补全。但是在项目完结的时候,是需要撰写这样的一个文档的。
 
可以参考Redis源码中Readme的写法,这里面简洁清晰的描述了Redis功能和源码结构。

关于requirements.txt和setup.py

setup.py
 
一般来说,用setup.py来管理代码的打包、安装、部署问题。业界标准的写法是用Python流行的打包工具setuptools 来管理这些事情。这种方式普遍应用于开源项目中。不过这里的核心思想不是用标准化的工具来解决这些问题,而是说,一个项目一定要有一个安装部署工具,能快速便捷的在一台新机器上将环境装好、代码部署好和将程序运行起来。
 
我想大多数人是踩过坑的,刚开始接触Python写项目的时候,安装环境、部署代码、运行程序这个过程全是手动完成,遇到过以下问题:
安装环境时经常忘了最近又添加了一个新的Python包,结果一到线上运行,程序就出错了。Python包的版本依赖问题,有时候我们程序中使用的是一个版本的Python包,但是官方的已经是最新的包了,通过手动安装就可能装错了。如果依赖的包很多的话,一个一个安装这些依赖是很费时的事情。新同学开始写项目的时候,将程序跑起来非常麻烦,因为可能经常忘了要怎么安装各种依赖。
setup.py可以将这些事情自动化起来,提高效率、减少出错的概率。"复杂的东西自动化,能自动化的东西一定要自动化。"是一个非常好的习惯。

setuptools的文档比较庞大,刚接触的话,可能不太好找到切入点。学习技术的方式就是看他人是怎么用的,可以参考一下Python的一个Web框架,flask是如何写的:setup.py 。
 
当然,简单点自己写个安装脚本(deploy.sh)替代setup.py也未尝不可。

requirements.txt

这个文件存在的目的是:
方便开发者维护软件的包依赖。将开发过程中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包。方便读者明确项目使用了哪些Python包。
这个文件的格式是每一行包含一个包依赖的说明,通常是flask>=0.10这种格式,要求是这个格式能被pip识别,这样就可以简单的通过 pip install -r requirements.txt来把所有Python包依赖都装好了。具体格式说明参考 。
 
关于配置文件的使用方法
注意,在上面的目录结构中,没有将conf.py放在源码目录下,而是放在docs/目录下。
 
很多项目对配置文件的使用做法是:
配置文件写在一个或多个python文件中,比如此处的conf.py。项目中哪个模块用到这个配置文件就直接通过import conf这种形式来在代码中使用配置。
 
这种做法我不太赞同:
这让单元测试变得困难(因为模块内部依赖了外部配置)另一方面配置文件作为用户控制程序的接口,应当可以由用户自由指定该文件的路径。程序组件可复用性太差,因为这种贯穿所有模块的代码硬编码方式,使得大部分模块都依赖conf.py这个文件。
 
所以,我认为配置的使用,更好的方式:
模块的配置都是可以灵活配置的,不受外部配置文件的影响。程序的配置也是可以灵活控制的。
 
能够佐证这个思想的是,用过nginx和mysql的同学都知道,nginx、mysql这些程序都可以自由的指定用户配置。

所以,不应当在代码中直接import conf来使用配置文件。上面目录结构中的conf.py,是给出的一个配置样例,不是在写死在程序中直接引用的配置文件。可以通过给main.py启动参数指定配置路径的方式来让程序读取配置内容。当然,这里的conf.py你可以换个类似的名字,比如settings.py。或者你也可以使用其他格式的内容来编写配置文件,比如settings.yaml之类的。 查看全部


为什么要设计好目录结构?


"设计项目目录结构",就和"代码编码风格"一样,属于个人风格问题。对于这种风格上的规范,一直都存在两种态度:
  1. 一类同学认为,这种个人风格问题"无关紧要"。理由是能让程序work就好,风格问题根本不是问题;
  2. 另一类同学认为,规范化能更好的控制程序结构,让程序具有更高的可读性。

 
我是比较偏向于后者的,因为我是前一类同学思想行为下的直接受害者。我曾经维护过一个非常不好读的项目,其实现的逻辑并不复杂,但是却耗费了我非常长的时间去理解它想表达的意思。从此我个人对于提高项目可读性、可维护性的要求就很高了。"项目目录结构"其实也是属于"可读性和可维护性"的范畴,我们设计一个层次清晰的目录结构,就是为了达到以下两点:
  1. 可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。
  2. 可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。

 
所以,保持一个层次清晰的目录结构是有必要的。更何况组织一个良好的工程目录,其实是一件很简单的事儿。
 


目录组织方式


关于如何组织一个较好的Python工程目录结构,已经有一些得到了共识的目录结构。在Stackoverflow关于这个问题 ,可以看到很多赞同对Python目录结构规范的情况。

假设你的项目名为foo, 我比较建议的最方便快捷目录结构这样就足够了:
Foo/
|-- bin/
| |-- foo
|
|-- foo/
| |-- tests/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- docs/
| |-- conf.py
| |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README
简要解释一下:
  1. bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。
  2. foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py。
  3. docs/: 存放一些文档。
  4. setup.py: 安装、部署、打包的脚本。
  5. requirements.txt: 存放软件依赖的外部Python包列表。
  6. README: 项目说明文件。

 
除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,ChangeLog.txt文件等,我没有列在这里,因为这些东西主要是项目开源的时候需要用到。如果你想写一个开源软件,目录该如何组织,可以参考开源Python项目的正确方法 。


关于README的内容 


这个我觉得是每个项目都应该有的一个文件,目的是能简要描述该项目的信息,让读者快速了解这个项目。
 
它需要说明以下几个事项:
  1. 软件定位,软件的基本功能。
  2. 运行代码的方法: 安装环境、启动命令等。
  3. 简要的使用说明。
  4. 代码目录结构说明,更详细点可以说明软件的基本原理。
  5. 常见问题说明。

我觉得有以上几点是比较好的一个README。在软件开发初期,由于开发过程中以上内容可能不明确或者发生变化,并不是一定要在一开始就将所有信息都补全。但是在项目完结的时候,是需要撰写这样的一个文档的。
 
可以参考Redis源码中Readme的写法,这里面简洁清晰的描述了Redis功能和源码结构。


关于requirements.txt和setup.py


setup.py
 
一般来说,用setup.py来管理代码的打包、安装、部署问题。业界标准的写法是用Python流行的打包工具setuptools 来管理这些事情。这种方式普遍应用于开源项目中。不过这里的核心思想不是用标准化的工具来解决这些问题,而是说,一个项目一定要有一个安装部署工具,能快速便捷的在一台新机器上将环境装好、代码部署好和将程序运行起来。
 
我想大多数人是踩过坑的,刚开始接触Python写项目的时候,安装环境、部署代码、运行程序这个过程全是手动完成,遇到过以下问题:
  1. 安装环境时经常忘了最近又添加了一个新的Python包,结果一到线上运行,程序就出错了。
  2. Python包的版本依赖问题,有时候我们程序中使用的是一个版本的Python包,但是官方的已经是最新的包了,通过手动安装就可能装错了。
  3. 如果依赖的包很多的话,一个一个安装这些依赖是很费时的事情。
  4. 新同学开始写项目的时候,将程序跑起来非常麻烦,因为可能经常忘了要怎么安装各种依赖。

setup.py可以将这些事情自动化起来,提高效率、减少出错的概率。"复杂的东西自动化,能自动化的东西一定要自动化。"是一个非常好的习惯。

setuptools的文档比较庞大,刚接触的话,可能不太好找到切入点。学习技术的方式就是看他人是怎么用的,可以参考一下Python的一个Web框架,flask是如何写的:setup.py 。
 
当然,简单点自己写个安装脚本(deploy.sh)替代setup.py也未尝不可。


requirements.txt


这个文件存在的目的是:
  1. 方便开发者维护软件的包依赖。将开发过程中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包。
  2. 方便读者明确项目使用了哪些Python包。

这个文件的格式是每一行包含一个包依赖的说明,通常是flask>=0.10这种格式,要求是这个格式能被pip识别,这样就可以简单的通过 pip install -r requirements.txt来把所有Python包依赖都装好了。具体格式说明参考 。
 
关于配置文件的使用方法
注意,在上面的目录结构中,没有将conf.py放在源码目录下,而是放在docs/目录下。
 
很多项目对配置文件的使用做法是:
  1. 配置文件写在一个或多个python文件中,比如此处的conf.py。
  2. 项目中哪个模块用到这个配置文件就直接通过import conf这种形式来在代码中使用配置。

 
这种做法我不太赞同:
  1. 这让单元测试变得困难(因为模块内部依赖了外部配置)
  2. 另一方面配置文件作为用户控制程序的接口,应当可以由用户自由指定该文件的路径。
  3. 程序组件可复用性太差,因为这种贯穿所有模块的代码硬编码方式,使得大部分模块都依赖conf.py这个文件。

 
所以,我认为配置的使用,更好的方式:
  1. 模块的配置都是可以灵活配置的,不受外部配置文件的影响。
  2. 程序的配置也是可以灵活控制的。

 
能够佐证这个思想的是,用过nginx和mysql的同学都知道,nginx、mysql这些程序都可以自由的指定用户配置。

所以,不应当在代码中直接import conf来使用配置文件。上面目录结构中的conf.py,是给出的一个配置样例,不是在写死在程序中直接引用的配置文件。可以通过给main.py启动参数指定配置路径的方式来让程序读取配置内容。当然,这里的conf.py你可以换个类似的名字,比如settings.py。或者你也可以使用其他格式的内容来编写配置文件,比如settings.yaml之类的。

Python编码解析

采菊篱下 发表了文章 • 0 个评论 • 682 次浏览 • 2016-09-09 17:38 • 来自相关话题

一般我们在Python2.7的环境进行Python的编程的时候,一般头部会加#-*- coding:utf-8 -*- ​来声明编码类型为utf-8的编码,那为什么要声明,一定要声明吗?

针对如上问题我们先来讨论另外一个问题,为什么我们可以在显示器上能看到这些文字、数字、图片、字符、等等信息呢?大家都知道计算机本身只能识别 0  1 的组合,他们是怎么展示这些内容的呢?我们怎么和计算机去沟通呢?

如果我们使用0 1 的组合和计算机沟通你还能看到这些内容吗?还有一个问题就是01的组合我相信对于常人类都是没有办法看懂的。

那怎么办?如何让计算机理解我们的语言,并且我们能理解计算机的语言呢?

举个比较形象的例子,中英文词典对照表,这样我们就可以把中英文进行互相的翻译了呢?对不对!同理计算机也是这样的他需要一个标准的对照关系,那么这个标准最早叫什么呢?ASCII表




表格内容大致如下:
有特殊符号、大写字母、小写字母、数字(这里注意下0~9的数字是字符),在这些字符左边都有一个10进制的数字。但是对于10进制来说计算机他也是不能理解的,因为他只能理解0 1 ,但是10进制和2进制的转换就非常容易了!

举例来说:如果我在键盘上按一个A字母的时候那么实际是给计算机传输了一个数字65,通过这样的机制和计算机沟通,有了这个ASCII码表就可以和任何计算机进行沟通了。

这里在看个知识点:计算机中最小的单位是什么?bit   bit就咱们常说一位二进制,一位二进制要么是0 要么是 1

但是bit这个单位太小了,我们用字节(byte)来表示。他们是有换算的规则的(看下面的规则我想大家都不是很陌生对吧):8b = 1B #小b=bit ; 大B=byte
1024B = 1KB
1024KB = 1M
1024M = 1G
1024G = 1T 在存储英文的时候我们至少需要1个字节(一个字母),就是8位(bit),看下ASCII表中1个字节就可以表示所有的英文所需要的字符,是不非常高效!

为什么呢?早期的计算机的空间是非常宝贵的!

那你会发现1个字节8位,他能存储的最大数据是2的8次方-1 = 255,一个字节最多能表示255个字符 那西方国家他们使用了127个字符,那么剩下字符是做什么的呢?就是用来做扩展的,西方人考虑到还有其他国家。所以留下了扩展位。

但是呢有问题,计算机是西方人发明的,如果仅仅支持英文的话,这127个字符完全就可以表示所有英文中能用的的内容了。但是他没有考虑咱们大中国啊!ASCII到了中国之后发现:咱们中国最常用的中文都有6000多个完全不够用啊!

但是怎们办?中国人非常聪明:就在原有的扩展位中,扩展出自己的gbk、gb2312、gb2318字符编码。 

他是怎么扩展的呢?比如说在ASCII码中的128这个位置,这个位置又指定一张单独表,聪明吧! 其他国家也是这样设计的!

中国东亚大国是吧,我们国家比较NB,我要兼容其他国家的常用的编码!比如韩国日本,因为韩国和日本人家都有自己的编码,人家根本就不鸟你,举个例子来说,比如韩国的游戏,在中国下载安装之后会出现乱码的情况?什么鬼?

这种乱码的出现基本上就两种情况:
1、字符编码没有
2、字符编码冲突了,人家在写这个程序的时候指定的字符集和咱们使用的字符集的位置不对。 

你想想不光是亚洲国家这样,欧洲国家,非洲国家都会存在这个问题,基于这个乱象国际互联网组织就说你们各个国家都别搞了,我们给你们搞一个统一的,这个统一的是什么呢Unicode“万国编码”。

Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,规定虽有的字符和符号最少由 16 位来表示(2个字节),即:2 **16 = 65536, 注:此处说的的是最少2个字节,可能更多。

这里还有个问题:使用的字节增加了,那么造成的直接影响就是使用的空间就直接翻倍了!举例还说:同样是ABCD这些字符存储一篇相同的文章,使用ASCII码如果是1M的话,那么Unicode存储至少2M可能还会更多。

为了解决个问题就出现了:UTF-8编码

UTF-8编码:是对Unicode编码的压缩和优化,他不再使用最少使用2个字节,而是将所有的字符和符号进行分类:ascii码中的内容用1个字节保存、欧洲的字符用2个字节保存,东亚的字符用3个字节保存...

通过这种可扩展的方式来存储。

OK 上面了解了:
1、什么ASCII编码
2、什么Unicode编码
3、什么UTF-8编码

回顾下乱码的出现原因:1、没有字符集 2、字符集冲突

回过头来看下为什么需要在第二行加上指定编码呢?在2.x版本的Python中Pyton在解释.py文件的时候,默认是给他一个编码的就是ASCII码,so如果在2.7版本中如果你不指定编码并且在.py文件中写了一个ASCII码中没有的字符就会显示乱码 。

不过这个问题在Python3中就不存在了,因为在Python3中默认就是Unicode编码。

Python编码转换

有一个问题,既然有统一的Unicode编码了,为毛还需要编码转换?大家都统一一个编码不就可以了吗?

不要问我为什么,我问你们个问题,如果世界上出了一种世界语言,你会放弃中文吗?去使用这个世界通用语言吗?这就是个坑,是个遗留问题。

但是虽然以后可能世界语言会慢慢替代咱们常用的语言,大家以后沟通就使用世界语言就不会有沟通障碍了对吧。(就是举个例子)

还有一个情况是什么呢?韩国的游戏到中国来之后,是乱码?结合上一个回答咱们可以猜出:编写这个游戏的人在编写游戏的时候可能根本就没有考虑出口其他国家。那如果没有这个Unicode编码的话,到咱们这里来显示肯定是乱码是吧。

那就得需要通过转码把他们编码集,转换为Unicode(utf-8)编码集。这样他们就可以正常显示韩文了!(这里只是转编码集并不是翻译成中文不要弄混了~~!)

Python3中的编码转换
#在Python3中默认就是unicode编码#!/usr/bin/env python3
# _*_coding:utf-8_*_
# Author: Lucky.chen

tim = '华仔'
#转为UTF-8编码
print(tim.encode('UTF-8'))

#转为GBK编码
print(tim.encode('GBK'))

#转为ASCII编码(报错为什么?因为ASCII码表中没有‘华仔’这个字符集~~)
print(tim.encode('ASCII'))



 
二、Python2.X中的编码转换
#因为在python2.X中默认是ASCII编码,你在文件中指定编码为UTF-8,但是UTF-8如果你想转GBK的话是不能直接转,需要Unicode做一个中间人转换角色。




#!/usr/bin/env python2
# _*_coding:utf-8_*_
# Author: Lucky.chen

import sys
print(sys.getdefaultencoding())


msg = "我爱北京天安门"
msg_gb2312 = msg.decode("utf-8").encode("gb2312")
gb2312_to_gbk = msg_gb2312.decode("gbk").encode("gbk")

print(msg)
print(msg_gb2312)
print(gb2312_to_gbk) 查看全部
一般我们在Python2.7的环境进行Python的编程的时候,一般头部会加#-*- coding:utf-8 -*- ​来声明编码类型为utf-8的编码,那为什么要声明,一定要声明吗?

针对如上问题我们先来讨论另外一个问题,为什么我们可以在显示器上能看到这些文字、数字、图片、字符、等等信息呢?大家都知道计算机本身只能识别 0  1 的组合,他们是怎么展示这些内容的呢?我们怎么和计算机去沟通呢?

如果我们使用0 1 的组合和计算机沟通你还能看到这些内容吗?还有一个问题就是01的组合我相信对于常人类都是没有办法看懂的。

那怎么办?如何让计算机理解我们的语言,并且我们能理解计算机的语言呢?

举个比较形象的例子,中英文词典对照表,这样我们就可以把中英文进行互相的翻译了呢?对不对!同理计算机也是这样的他需要一个标准的对照关系,那么这个标准最早叫什么呢?ASCII表
ascii.gif

表格内容大致如下:
有特殊符号、大写字母、小写字母、数字(这里注意下0~9的数字是字符),在这些字符左边都有一个10进制的数字。但是对于10进制来说计算机他也是不能理解的,因为他只能理解0 1 ,但是10进制和2进制的转换就非常容易了!

举例来说:如果我在键盘上按一个A字母的时候那么实际是给计算机传输了一个数字65,通过这样的机制和计算机沟通,有了这个ASCII码表就可以和任何计算机进行沟通了。

这里在看个知识点:计算机中最小的单位是什么?bit   bit就咱们常说一位二进制,一位二进制要么是0 要么是 1

但是bit这个单位太小了,我们用字节(byte)来表示。他们是有换算的规则的(看下面的规则我想大家都不是很陌生对吧):
8b = 1B  #小b=bit ; 大B=byte
1024B = 1KB
1024KB = 1M
1024M = 1G
1024G = 1T
在存储英文的时候我们至少需要1个字节(一个字母),就是8位(bit),看下ASCII表中1个字节就可以表示所有的英文所需要的字符,是不非常高效!

为什么呢?早期的计算机的空间是非常宝贵的!

那你会发现1个字节8位,他能存储的最大数据是2的8次方-1 = 255,一个字节最多能表示255个字符 那西方国家他们使用了127个字符,那么剩下字符是做什么的呢?就是用来做扩展的,西方人考虑到还有其他国家。所以留下了扩展位。

但是呢有问题,计算机是西方人发明的,如果仅仅支持英文的话,这127个字符完全就可以表示所有英文中能用的的内容了。但是他没有考虑咱们大中国啊!ASCII到了中国之后发现:咱们中国最常用的中文都有6000多个完全不够用啊!

但是怎们办?中国人非常聪明:就在原有的扩展位中,扩展出自己的gbk、gb2312、gb2318字符编码。 

他是怎么扩展的呢?比如说在ASCII码中的128这个位置,这个位置又指定一张单独表,聪明吧! 其他国家也是这样设计的!

中国东亚大国是吧,我们国家比较NB,我要兼容其他国家的常用的编码!比如韩国日本,因为韩国和日本人家都有自己的编码,人家根本就不鸟你,举个例子来说,比如韩国的游戏,在中国下载安装之后会出现乱码的情况?什么鬼?

这种乱码的出现基本上就两种情况:
1、字符编码没有
2、字符编码冲突了,人家在写这个程序的时候指定的字符集和咱们使用的字符集的位置不对。 

你想想不光是亚洲国家这样,欧洲国家,非洲国家都会存在这个问题,基于这个乱象国际互联网组织就说你们各个国家都别搞了,我们给你们搞一个统一的,这个统一的是什么呢Unicode“万国编码”

Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,规定虽有的字符和符号最少由 16 位来表示(2个字节),即:2 **16 = 65536, 注:此处说的的是最少2个字节,可能更多。

这里还有个问题:使用的字节增加了,那么造成的直接影响就是使用的空间就直接翻倍了!举例还说:同样是ABCD这些字符存储一篇相同的文章,使用ASCII码如果是1M的话,那么Unicode存储至少2M可能还会更多。

为了解决个问题就出现了:UTF-8编码

UTF-8编码:是对Unicode编码的压缩和优化,他不再使用最少使用2个字节,而是将所有的字符和符号进行分类:ascii码中的内容用1个字节保存、欧洲的字符用2个字节保存,东亚的字符用3个字节保存...

通过这种可扩展的方式来存储。

OK 上面了解了:
1、什么ASCII编码
2、什么Unicode编码
3、什么UTF-8编码

回顾下乱码的出现原因:1、没有字符集 2、字符集冲突

回过头来看下为什么需要在第二行加上指定编码呢?在2.x版本的Python中Pyton在解释.py文件的时候,默认是给他一个编码的就是ASCII码,so如果在2.7版本中如果你不指定编码并且在.py文件中写了一个ASCII码中没有的字符就会显示乱码 。

不过这个问题在Python3中就不存在了,因为在Python3中默认就是Unicode编码。


Python编码转换


有一个问题,既然有统一的Unicode编码了,为毛还需要编码转换?大家都统一一个编码不就可以了吗?

不要问我为什么,我问你们个问题,如果世界上出了一种世界语言,你会放弃中文吗?去使用这个世界通用语言吗?这就是个坑,是个遗留问题。

但是虽然以后可能世界语言会慢慢替代咱们常用的语言,大家以后沟通就使用世界语言就不会有沟通障碍了对吧。(就是举个例子)

还有一个情况是什么呢?韩国的游戏到中国来之后,是乱码?结合上一个回答咱们可以猜出:编写这个游戏的人在编写游戏的时候可能根本就没有考虑出口其他国家。那如果没有这个Unicode编码的话,到咱们这里来显示肯定是乱码是吧。

那就得需要通过转码把他们编码集,转换为Unicode(utf-8)编码集。这样他们就可以正常显示韩文了!(这里只是转编码集并不是翻译成中文不要弄混了~~!)

Python3中的编码转换
#在Python3中默认就是unicode编码
#!/usr/bin/env python3
# _*_coding:utf-8_*_
# Author: Lucky.chen

tim = '华仔'
#转为UTF-8编码
print(tim.encode('UTF-8'))

#转为GBK编码
print(tim.encode('GBK'))

#转为ASCII编码(报错为什么?因为ASCII码表中没有‘华仔’这个字符集~~)
print(tim.encode('ASCII'))
EncodeError.png

 
二、Python2.X中的编码转换
#因为在python2.X中默认是ASCII编码,你在文件中指定编码为UTF-8,但是UTF-8如果你想转GBK的话是不能直接转,需要Unicode做一个中间人转换角色。
decode.png

#!/usr/bin/env python2
# _*_coding:utf-8_*_
# Author: Lucky.chen

import sys
print(sys.getdefaultencoding())


msg = "我爱北京天安门"
msg_gb2312 = msg.decode("utf-8").encode("gb2312")
gb2312_to_gbk = msg_gb2312.decode("gbk").encode("gbk")

print(msg)
print(msg_gb2312)
print(gb2312_to_gbk)

Python使用正则收集IP信息

Not see︶ 发表了文章 • 0 个评论 • 585 次浏览 • 2016-08-24 14:38 • 来自相关话题

#!/usr/bin/env python

import re
from subprocess import Popen, PIPE

def getIfconfig():
p = Popen(['ifconfig'], stdout=PIPE)
data = p.stdout.read().split('\n\n')
return [i for i in data if i and not i.startswith('lo')]

def parseIfconfig(data):
re_devname = re.compile(r'(br|eth|em|virbr|lo|bond)[\d:]+',re.M)
re_mac = re.compile(r'HWaddr ([0-9A-F:]{17})', re.M)
re_ip = re.compile('inet addr:([\d\.]{7,15})', re.M)
devname = re_devname.search(data)
if devname:
devname = devname.group()
else:
devname = ''
mac = re_mac.search(data)
if mac:
mac = mac.group(1)
else:
mac = ''
ip = re_ip.search(data)
if ip:
ip = ip.group(1)
else:
ip = ''
return {devname: [ip, mac]}

if __name__ == '__main__':
data = getIfconfig()
for i in data:
print parseIfconfig(i) 查看全部
#!/usr/bin/env python

import re
from subprocess import Popen, PIPE

def getIfconfig():
p = Popen(['ifconfig'], stdout=PIPE)
data = p.stdout.read().split('\n\n')
return [i for i in data if i and not i.startswith('lo')]

def parseIfconfig(data):
re_devname = re.compile(r'(br|eth|em|virbr|lo|bond)[\d:]+',re.M)
re_mac = re.compile(r'HWaddr ([0-9A-F:]{17})', re.M)
re_ip = re.compile('inet addr:([\d\.]{7,15})', re.M)
devname = re_devname.search(data)
if devname:
devname = devname.group()
else:
devname = ''
mac = re_mac.search(data)
if mac:
mac = mac.group(1)
else:
mac = ''
ip = re_ip.search(data)
if ip:
ip = ip.group(1)
else:
ip = ''
return {devname: [ip, mac]}

if __name__ == '__main__':
data = getIfconfig()
for i in data:
print parseIfconfig(i)

Python3中异常处理常用的三种方法

小白菜 发表了文章 • 0 个评论 • 733 次浏览 • 2016-08-22 23:13 • 来自相关话题

一般我们我们想捕获python的异常写入到log,做处理的话,一般用try语句来做处理,大概语法如下:try:
语句1
语句2
.
.
语句N
except ........ :
do something .......但是你并不知道"语句1至语句N"哪个会出现什么样的错误,但你还要做异常处理,且想把出现的异常打印出来,并不停止程序的运行,所以在"except ......"语句就起作用了。
 
方法一:捕获所有异常Python2如下:
try:
语句1
语句2
.....
语句N
except Exception,e:
print Exception,":",e

Python3如下:
try:
语句1
语句2
.....
语句N
except Exception as e:
print(Exception, ":", e)例子如下:try:
a = 1
b = a
c = w
except Exception as e:
print(Exception, ":", e)

结果为:
<class 'Exception'> : name 'w' is not defined
 方法二:采用sys模块回溯最后的异常
sys.exc_info() 会返回一个3值元表,其中包含调用该命令时捕获的异常。
这个元表的内容为 (type, value, traceback) ,其中:
type 从获取到的异常中得到类型名称,它是BaseException 的子类;value 是捕获到的异常实例;traceback 是一个 traceback 对象,下面会详述。
import sys
try:
w = abs(-1)
list.append(w)
except:
info = sys.exc_info()
print(info[0], ":", info[1])

# 结果如下:
<class 'TypeError'> : descriptor 'append' requires a 'list' object but received a 'int'sys.last_traceback 包含的内容与 sys.exc_info() 相同,但它主要用于调试,并不总是被定义。
 
三、采用traceback模块查看异常
trackback 模块用来精确模仿 python3 解析器的 stack trace 行为。在程序中应该尽量使用这个模块。
traceback.print_exc() 可以直接打印当前的异常。import traceback
try:
raise
except:
traceback.print_exc()traceback.print_tb() 用来打印上面提到的 trackback 对象。import sys,traceback
try:
raise
except:
t,v,tb = sys.exc_info()
traceback.print_tb(tb)traceback.print_exception() 可以直接打印 sys.exc_info()提供的元表。import sys,traceback
try:
raise
except:
traceback.print_exception(*sys.exc_info())其实,下面两句是等价的:
traceback.print_exc()traceback.print_exception(*sys.exc_info())
 
traceback 提供的参数可以将 print 的内容写入到文件中import traceback
try:
a=b
b=c
except:
f=open("log.txt",'a')
traceback.print_exc(file=f)
f.flush()
f.close()参考:
https://docs.python.org/3/library/traceback.html?highlight=print_tb#traceback.print_exc
https://docs.python.org/3/tutorial/errors.html 查看全部
一般我们我们想捕获python的异常写入到log,做处理的话,一般用try语句来做处理,大概语法如下:
try:
语句1
语句2
.
.
语句N
except ........ :
do something .......
但是你并不知道"语句1至语句N"哪个会出现什么样的错误,但你还要做异常处理,且想把出现的异常打印出来,并不停止程序的运行,所以在"except ......"语句就起作用了。
 
方法一:捕获所有异常
Python2如下:
try:
语句1
语句2
.....
语句N
except Exception,e:
print Exception,":",e

Python3如下:
try:
语句1
语句2
.....
语句N
except Exception as e:
print(Exception, ":", e)
例子如下:
try:
a = 1
b = a
c = w
except Exception as e:
print(Exception, ":", e)

结果为:
<class 'Exception'> : name 'w' is not defined

 方法二:采用sys模块回溯最后的异常
sys.exc_info() 会返回一个3值元表,其中包含调用该命令时捕获的异常。
这个元表的内容为 (type, value, traceback) ,其中:
  • type 从获取到的异常中得到类型名称,它是BaseException 的子类;
  • value 是捕获到的异常实例;
  • traceback 是一个 traceback 对象,下面会详述。

import sys
try:
w = abs(-1)
list.append(w)
except:
info = sys.exc_info()
print(info[0], ":", info[1])

# 结果如下:
<class 'TypeError'> : descriptor 'append' requires a 'list' object but received a 'int'
sys.last_traceback 包含的内容与 sys.exc_info() 相同,但它主要用于调试,并不总是被定义。
 
三、采用traceback模块查看异常
trackback 模块用来精确模仿 python3 解析器的 stack trace 行为。在程序中应该尽量使用这个模块。
traceback.print_exc() 可以直接打印当前的异常。
import traceback
try:
raise
except:
traceback.print_exc()
traceback.print_tb() 用来打印上面提到的 trackback 对象。
import sys,traceback
try:
raise
except:
t,v,tb = sys.exc_info()
traceback.print_tb(tb)
traceback.print_exception() 可以直接打印 sys.exc_info()提供的元表。
import sys,traceback
try:
raise
except:
traceback.print_exception(*sys.exc_info())
其实,下面两句是等价的:
  • traceback.print_exc()
  • traceback.print_exception(*sys.exc_info())

 
traceback 提供的参数可以将 print 的内容写入到文件中
import traceback
try:
a=b
b=c
except:
f=open("log.txt",'a')
traceback.print_exc(file=f)
f.flush()
f.close()
参考:
https://docs.python.org/3/library/traceback.html?highlight=print_tb#traceback.print_exc
https://docs.python.org/3/tutorial/errors.html

Python的生成器和迭代器

采菊篱下 发表了文章 • 0 个评论 • 501 次浏览 • 2016-08-19 18:39 • 来自相关话题

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
 
 
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
 
 
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:>>> L = [x * x for x in range(5)]
>>> L
[0, 1, 4, 9, 16]
>>> g = (x * x for x in range(5))
>>> g
<generator object <genexpr> at 0x10fe179e8>创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。

我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
>>> for i in g:
... print(i)
...
0
1
4
9
16
>>> for i in L:
... print(i)
...
0
1
4
9
16
如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:
>>> g = (x * x for x in range(5))
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

# 取完之后就会报错,因为取完了,就没有,异常关键字:StopIterationgenerator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

generator也是可迭代对象,所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
 
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'注意,赋值语句:a, b = b, a + b相当于:
t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]但不必显式写出临时变量t就可以赋值。

上面的函数可以输出斐波那契数列的前N个数:
>>> fib(10)
1
1
2
3
5
8
13
21
34
55
done仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
def fib(max):
n,a,b = 0,0,1

while n < max:
#print(b)
yield b
a,b = b,a+b

n += 1

return 'done' 这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
data = fib(10)
print(data)

print(data.__next__())
print(data.__next__())
print("干点别的事")
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())

#输出
<generator object fib at 0x101be02b0>
1
1
干点别的事
2
3
5
8
13在上面fib的例子,我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代:
 
>>> for n in fib(6):
... print(n)
...
1
1
2
3
5
8但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
>>> g = fib(6)
>>> while True:
... try:
... x = next(g)
... print('g:', x)
... except StopIteration as e:
... print('Generator return value:', e.value)
... break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done关于如何捕获错误,后面的错误处理还会详细讲解。

还可通过yield实现在单线程的情况下实现并发运算的效果
import time
def consumer(name):
print("%s 准备吃包子啦!" %name)
while True:
baozi = yield

print("包子[%s]来了,被[%s]吃了!" %(baozi,name))


def producer(name):
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print("开始准备做包子啦!")
for i in range(10):
time.sleep(1)
print("做了2个包子!")
c.send(i)
c2.send(i)

producer("lucky")

迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;一类是generator,包括生成器和带yield的generator function。这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

可以使用isinstance()判断一个对象是否是Iterable对象:
 
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
 
*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用isinstance()判断一个对象是否是Iterator对象:
>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True你可能会问,为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
 
小结
凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:
for x in [1, 2, 3, 4, 5]:
pass实际上完全等价于:
# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
try:
# 获得下一个值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循环
break 查看全部


生成器


通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
 
 
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
 
 
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
>>> L = [x * x for x in range(5)]
>>> L
[0, 1, 4, 9, 16]
>>> g = (x * x for x in range(5))
>>> g
<generator object <genexpr> at 0x10fe179e8>
创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。

我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
>>> for i in g:
... print(i)
...
0
1
4
9
16
>>> for i in L:
... print(i)
...
0
1
4
9
16

如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:
>>> g = (x * x for x in range(5))
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

# 取完之后就会报错,因为取完了,就没有,异常关键字:StopIteration
generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

generator也是可迭代对象,所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
 
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
注意,赋值语句:
a, b = b, a + b
相当于:
t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]
但不必显式写出临时变量t就可以赋值。

上面的函数可以输出斐波那契数列的前N个数:
>>> fib(10)
1
1
2
3
5
8
13
21
34
55
done
仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
def fib(max):
n,a,b = 0,0,1

while n < max:
#print(b)
yield b
a,b = b,a+b

n += 1

return 'done'
这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
data = fib(10)
print(data)

print(data.__next__())
print(data.__next__())
print("干点别的事")
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())

#输出
<generator object fib at 0x101be02b0>
1
1
干点别的事
2
3
5
8
13
在上面fib的例子,我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代:
 
>>> for n in fib(6):
... print(n)
...
1
1
2
3
5
8
但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
>>> g = fib(6)
>>> while True:
... try:
... x = next(g)
... print('g:', x)
... except StopIteration as e:
... print('Generator return value:', e.value)
... break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done
关于如何捕获错误,后面的错误处理还会详细讲解。

还可通过yield实现在单线程的情况下实现并发运算的效果
import time
def consumer(name):
print("%s 准备吃包子啦!" %name)
while True:
baozi = yield

print("包子[%s]来了,被[%s]吃了!" %(baozi,name))


def producer(name):
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print("开始准备做包子啦!")
for i in range(10):
time.sleep(1)
print("做了2个包子!")
c.send(i)
c2.send(i)

producer("lucky")


迭代器


我们已经知道,可以直接作用于for循环的数据类型有以下几种:
  • 一类是集合数据类型,如list、tuple、dict、set、str等;
  • 一类是generator,包括生成器和带yield的generator function。
  • 这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。


可以使用isinstance()判断一个对象是否是Iterable对象:
 
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
 
*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用isinstance()判断一个对象是否是Iterator对象:
>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True
你可能会问,为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
 
小结
凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:
for x in [1, 2, 3, 4, 5]:
pass
实际上完全等价于:
# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
try:
# 获得下一个值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循环
break

Python3内置函数介绍

采菊篱下 发表了文章 • 0 个评论 • 621 次浏览 • 2016-08-19 17:28 • 来自相关话题

详情参考:https://docs.python.org/3/library/functions.html​ 
 
1、abs(x)(返回一个数的绝对值)
>>> abs(-12)
12
>>> abs(-12.89)
12.89
>>> abs(-0.1)
0.1 
2、all(iterable) 
all会循环括号内的每一个元素,如果括号内的所有元素都是真的,则返回True,如果有一个为假的那么就返回False
>>> all([0, 3])
False
>>> all([1, 3])
True
>>> all([1, ""])
False一假则假,假的参数有:False、0、None、""、[]、()、{}等。
查看一个元素是否为假可以使用bool进行查看:
>>> bool("")
False
>>> bool(())
False
>>> bool(0)
False
>>> bool(1)
True
3、any(iterable)
循环元素,如果有一个元素为真,那么就返回真,一真则真。
>>> any([0, 1, 2, 3])
True
>>> any([{}, (), 0])
False
4、ascii(object)
在对象的类中寻找__repr__方法,获取返回值
 
 
>>> class Foo:
... def __repr_(self):
... return "Result"
...
>>> obj = Foo()
>>> r = ascii(obj)
>>> print(r)
<__main__.Foo object at 0x1045075c0>
5、bin(x)
将整数x转换为二进制字符串,如果x不为Python中int类型,x必须包含方法index()并且返回值为integer
 
# 返回一个整数的二进制
>>> bin(999)
'0b1111100111'# 非整型的情况,必须包含__index__()方法切返回值为integer的类型
>>> class myType:
... def __index__(self):
... return 35
...
>>> myvar = myType()
>>> bin(myvar)
'0b100011'
6、bool([x])
查看一个元素的布尔值,非真即假
>>> bool([])
False
>>> bool(0)
False
>>> bool(1)
True
7、bytearray([source [, encoding [, errors]]])
bytearray([source [, encoding [, errors]]])返回一个byte数组。Bytearray类型是一个可变的序列,并且序列中的元素的取值范围为 [0 ,255]。
 
source参数:
如果source为整数,则返回一个长度为source的初始化数组;如果source为字符串,则按照指定的encoding将字符串转换为字节序列;如果source为可迭代类型,则元素必须为[0 ,255]中的整数;如果source为与buffer接口一致的对象,则此对象也可以被用于初始化bytearray。
 
>>> bytearray(3)
bytearray(b'\x00\x00\x00')
8、bytes([source[, encoding[, errors]]])
>>> bytes("asdasd",encoding="utf-8")
b'asdasd'返回一个bytes类型。
 
9、callable(object)
返回一个对象是否可以被执行
 
>>> def func():
... return 123
...
>>> callable(func)
True
>>> func = 123
>>> callable(func)
False
10、chr(i)
返回一个数字在ASCII编码中对应的字符,取值范围256个
>>> chr(66)
'B'
>>> chr(5)
'\x05'
>>> chr(55)
'7'
>>> chr(255)
'\xff'
>>> chr(25)
'\x19'
>>> chr(65)
'A'
11、compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
把字符串编译成python可执行的代码
 
>>> str = "for i in range(0,6): print(i)"
>>> c = compile(str, '', 'exec')
>>> exec(c)
0
1
2
3
4
5
 
12、complex([real[, imag]])
创建一个值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数
>>> complex(1, 2)
(1+2j)
# 数字
>>> complex(1)
(1+0j)
# 当做字符串处理
>>> complex("1")
(1+0j)
# 注意:这个地方在“+”号两边不能有空格,也就是不能写成"1 + 2j",应该是"1+2j",否则会报错
>>> complex("1+2j")
(1+2j)
13、dict(**kwarg)
创建一个数据类型为字典
 
>>> dic = dict({"k1":"123","k2":"456"})
>>> dic
{'k1': '123', 'k2': '456'}
14、dir([object])
返回一个类中的所有方法
 
>>> a = [1, 2, 3, 4]
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
15、divmod(a, b)
divmod(a,b)方法返回的是a//b(除法取整)以及a对b的余数,返回结果类型为tuple
 
 
>>> divmod(10, 3)
(3, 1)
16、enumerate(iterable, start=0)
遍历可迭代的数据类型,为元素生成下标
>>> a = [0, 1, 2, 3]
>>> for n, k in enumerate(a):
... print(n, k)
...
0 0
1 1
2 2
3 3
17、eval(expression, globals=None, locals=None)
把一个字符串当作一个表达式去执行
>>> string = "1 + 3"
>>> string
'1 + 3'
>>> eval(string)
4

 
18、exec(object[, globals[, locals]])
把字符串当作python代码执行
>>> exec("for n in range(5): print(n)")
0
1
2
3
4
19、filter(function, iterable)
筛选过滤,循环可迭代的对象,把迭代的对象当作函数的参数,如果符合条件就返回True,否则就返回False
>>> def func(x):
... if x == 11 or x == 22:
... return True
...
>>> ret = filter(func,[11,22,33,44])
>>> for n in ret:
... print(n)
...
11
22
20、float([x])
将整数和字符串转换成浮点数
>>> float("124")
124.0
>>> float("123.45")
123.45
>>> float("-123.34")
-123.34

 
21、format(value[, format_spec]) 
字符串格式化
>>> a = "My name is {0}, age is {1}".format('lucky', 18)
>>> print(a)
My name is lucky, age is 18
22、frozenset([iterable])
frozenset是冻结的集合,它是不可变的,存在哈希值,好处是它可以作为字典的key,也可以作为其它集合的元素。缺点是一旦创建便不能更改,没有add,remove方法。
 
23、globals()
获取当前scripts文件内的所有全局变量
 
>>> a = 3
>>> bsd = "54asd"
>>> globals()
{'__doc__': None, 'bsd': '54asd', '__package__': None, 'a': 3, '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__loader__': <class '_frozen_importlib.BuiltinImporter'>}
24、hash(object)
返回一个对象的hash值
 
>>> a = "asdadasdwqeq234sdfdf"
>>> hash(a)
5390438057823015497
25、help([object])
查看一个类的所有详细方法
 
>>> help(list)
Help on class list in module __builtin__:

class list(object)
| list() -> new empty list
| list(iterable) -> new list initialized from iterable's items
|
| Methods defined here:
|
| __add__(...)
| x.__add__(y) <==> x+y
|
| __contains__(...)
| x.__contains__(y) <==> y in x
|
| __delitem__(...)
| x.__delitem__(y) <==> del x[y]
|
| __delslice__(...)
| x.__delslice__(i, j) <==> del x[i:j]
|
| Use of negative indices is not supported.
..........
26、hex(x)
获取一个数的十六进制
 
>>> hex(13)
'0xd'
27、id(object)
返回一个对象的内存地址
>>> a = 123
>>> id(a)
1835400816
28、input([prompt])
交互式输入
 
 
29、int(x, base=10)
获取一个数的十进制
>>> int("31")
31
30、isinstance(object, classinfo)
判断对象是否是这个类创建的
 
>>> li = [11,22,33]
>>> isinstance(li,list)
True
31、issubclass(class, classinfo)
查看一个对象是否为子类
 
32、iter(object[, sentinel])
创建一个可迭代的对象
>>> obj = iter([11,22,33,44])
>>> obj
<list_iterator object at 0x000002477DB25198>
>>> for n in obj:
... print(n)
...
11
22
33
44

 
33、len(s)
查看一个对象的长度
 
>>> name = 'lucky'
>>> len(name)
5
34、list([iterable])
创建一个数据类型为列表
>>> li = list([11,22,33,44])
>>> li
[11, 22, 33, 44]
35、locals()
返回当前scripts的局部变量,返回结果为字典格式
>>> def func():
... name="lucky"
... print(locals())
...
>>> func()
{'name': 'lucky'}
 
 
36、map(function, iterable, …)
把可迭代的对象作为函数的值
 
>>> ret = map(lambda x: x + 100, [1, 2, 3, 4, 5])
>>> for n in ret:
... print(n)
...
101
102
103
104
105
37、max(iterable, *[, key, default]) max(arg1, arg2, *args[, key])
获取一个对象中的最大值
 
>>> li = [1, 3, 5, 9 ,3]
>>> max(li)
9
38、min(iterable, *[, key, default])  min(arg1, arg2, *args[, key])
获取一个对象中的最小值
>>> li = list([11,22,33,44])
>>> li = [11,22,33,44]
>>> min(li)
11
39、next(iterator[, default])
 
每次只拿取可迭代对象的一个元素
 
>>> obj = iter([11,22,33,44])
>>> next(obj)
11
>>> next(obj)
22
>>> next(obj)
33
>>> next(obj)
44
>>> next(obj)
# 如果没有可迭代的元素了就会报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
40、oct(x)
获取一个字符串的八进制
>>> oct(13)
'0o15'
41、open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
文件操作的函数,用来做文件操作的
 
 
 
42、ord(c)
把一个字母转换为ASCII对对应表中的数字
 
>>> ord("a")
97
>>> ord("t")
116
43、pow(x, y[, z])
返回一个数的N次方
>>> pow(2, 10)
1024
>>> pow(2, 20)
1048576
 
44、print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)
打印输出
 
 
45、range(start, stop[, step])
生成一个可迭代序列
 
>>> range(10)
range(0, 10)
>>> for n in range(5):
... print(n)
...
0
1
2
3
4
46、reversed(seq)
对一个对象的元素进行反转
>>> li = [1, 2, 3, 4]
>>> reversed(li)
<list_reverseiterator object at 0x000002CF0EF6A940>
>>> for n in reversed(li):
... print(n)
...
4
3
2
1
47、round(number[, ndigits])
四舍五入
>>> round(3.3)
3
>>> round(3.7)
4
48、set([iterable])
创建一个数据类型为集合
>>> varss = set([11,222,333])
>>> type(varss)
<class 'set'>
49、slice(start, stop[, step])
元素的切片操作都是调用的这个方法
 
50、sorted(iterable[, key][, reverse])
为一个对象的元素进行排序
 
>>> li = [ 2, 3, 4, 9, 1, 100]
>>> sorted(li)
[1, 2, 3, 4, 9, 100]
51、sum(iterable[, start])
求和
>>> sum([11,22,33])
66
52、type(object)
查看一个对象的数据类型
 
>>> a = 1
>>> type(a)
<class 'int'>
>>> a = "str"
>>> type(a)
<class 'str'>
53、vars([object])
查看一个对象里面有多少个变量
 
54、zip(*iterables)
联合迭代
>>> li1 = ["k1","k2","k3"]
>>> li2 = ["a","b","c"]
>>> zip(li1,li2)
<zip object at 0x0000026BF1803288>
>>> dic = zip(li1,li2)
>>> for n in dic:
... print(n)
...
('k1', 'a')
('k2', 'b')
('k3', 'c')
55、import(name, globals=None, locals=None, fromlist=(), level=0)
导入模块,把导入的模块作为一个别名。
生成一个六位的随机验证码,且包含数字,数字的位置随机:
# 导入random模块
import random
temp = ""
for i in range(6):
num = random.randrange(0,4)
if num == 3 or num == 1:
rad2 = random.randrange(0,10)
temp = temp + str(rad2)
else:
rad1 = random.randrange(65,91)
c1 = chr(rad1)
temp = temp + c1
print(temp) 查看全部
intfunc.png

详情参考:https://docs.python.org/3/library/functions.html​ 
 
1、abs(x)(返回一个数的绝对值)
>>> abs(-12)
12
>>> abs(-12.89)
12.89
>>> abs(-0.1)
0.1
 
2、all(iterable) 
all会循环括号内的每一个元素,如果括号内的所有元素都是真的,则返回True,如果有一个为假的那么就返回False
>>> all([0, 3])
False
>>> all([1, 3])
True
>>> all([1, ""])
False
一假则假,假的参数有:False、0、None、""、[]、()、{}等。
查看一个元素是否为假可以使用bool进行查看:
>>> bool("")
False
>>> bool(())
False
>>> bool(0)
False
>>> bool(1)
True

3、any(iterable)
循环元素,如果有一个元素为真,那么就返回真,一真则真。
>>> any([0, 1, 2, 3])
True
>>> any([{}, (), 0])
False

4、ascii(object)
在对象的类中寻找__repr__方法,获取返回值
 
 
>>> class Foo:
... def __repr_(self):
... return "Result"
...
>>> obj = Foo()
>>> r = ascii(obj)
>>> print(r)
<__main__.Foo object at 0x1045075c0>

5、bin(x)
将整数x转换为二进制字符串,如果x不为Python中int类型,x必须包含方法index()并且返回值为integer
 
# 返回一个整数的二进制
>>> bin(999)
'0b1111100111'
# 非整型的情况,必须包含__index__()方法切返回值为integer的类型
>>> class myType:
... def __index__(self):
... return 35
...
>>> myvar = myType()
>>> bin(myvar)
'0b100011'

6、bool([x])
查看一个元素的布尔值,非真即假
>>> bool([])
False
>>> bool(0)
False
>>> bool(1)
True

7、bytearray([source [, encoding [, errors]]])
bytearray([source [, encoding [, errors]]])返回一个byte数组。Bytearray类型是一个可变的序列,并且序列中的元素的取值范围为 [0 ,255]。
 
source参数:
  • 如果source为整数,则返回一个长度为source的初始化数组;
  • 如果source为字符串,则按照指定的encoding将字符串转换为字节序列;
  • 如果source为可迭代类型,则元素必须为[0 ,255]中的整数;
  • 如果source为与buffer接口一致的对象,则此对象也可以被用于初始化bytearray。

 
>>> bytearray(3)
bytearray(b'\x00\x00\x00')

8、bytes([source[, encoding[, errors]]])
>>> bytes("asdasd",encoding="utf-8")
b'asdasd'
返回一个bytes类型。
 
9、callable(object)
返回一个对象是否可以被执行
 
>>> def func():
... return 123
...
>>> callable(func)
True
>>> func = 123
>>> callable(func)
False

10、chr(i)
返回一个数字在ASCII编码中对应的字符,取值范围256个
>>> chr(66)
'B'
>>> chr(5)
'\x05'
>>> chr(55)
'7'
>>> chr(255)
'\xff'
>>> chr(25)
'\x19'
>>> chr(65)
'A'

11、compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
把字符串编译成python可执行的代码
 
>>> str = "for i in range(0,6): print(i)"
>>> c = compile(str, '', 'exec')
>>> exec(c)
0
1
2
3
4
5

 
12、complex([real[, imag]])
创建一个值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数
>>> complex(1, 2)
(1+2j)
# 数字
>>> complex(1)
(1+0j)
# 当做字符串处理
>>> complex("1")
(1+0j)
# 注意:这个地方在“+”号两边不能有空格,也就是不能写成"1 + 2j",应该是"1+2j",否则会报错
>>> complex("1+2j")
(1+2j)

13、dict(**kwarg)
创建一个数据类型为字典
 
>>> dic = dict({"k1":"123","k2":"456"})
>>> dic
{'k1': '123', 'k2': '456'}

14、dir([object])
返回一个类中的所有方法
 
>>> a = [1, 2, 3, 4]
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

15、divmod(a, b)
divmod(a,b)方法返回的是a//b(除法取整)以及a对b的余数,返回结果类型为tuple
 
 
>>> divmod(10, 3)
(3, 1)

16、enumerate(iterable, start=0)
遍历可迭代的数据类型,为元素生成下标
>>> a = [0, 1, 2, 3]
>>> for n, k in enumerate(a):
... print(n, k)
...
0 0
1 1
2 2
3 3

17、eval(expression, globals=None, locals=None)
把一个字符串当作一个表达式去执行
>>> string = "1 + 3"
>>> string
'1 + 3'
>>> eval(string)
4

 
18、exec(object[, globals[, locals]])
把字符串当作python代码执行
>>> exec("for n in range(5): print(n)")
0
1
2
3
4

19、filter(function, iterable)
筛选过滤,循环可迭代的对象,把迭代的对象当作函数的参数,如果符合条件就返回True,否则就返回False
>>> def func(x):
... if x == 11 or x == 22:
... return True
...
>>> ret = filter(func,[11,22,33,44])
>>> for n in ret:
... print(n)
...
11
22

20、float([x])
将整数和字符串转换成浮点数
>>> float("124")
124.0
>>> float("123.45")
123.45
>>> float("-123.34")
-123.34

 
21、format(value[, format_spec]) 
字符串格式化
>>> a = "My name is {0}, age is {1}".format('lucky', 18)
>>> print(a)
My name is lucky, age is 18

22、frozenset([iterable])
frozenset是冻结的集合,它是不可变的,存在哈希值,好处是它可以作为字典的key,也可以作为其它集合的元素。缺点是一旦创建便不能更改,没有add,remove方法。
 
23、globals()
获取当前scripts文件内的所有全局变量
 
>>> a = 3
>>> bsd = "54asd"
>>> globals()
{'__doc__': None, 'bsd': '54asd', '__package__': None, 'a': 3, '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__loader__': <class '_frozen_importlib.BuiltinImporter'>}

24、hash(object)
返回一个对象的hash值
 
>>> a = "asdadasdwqeq234sdfdf"
>>> hash(a)
5390438057823015497

25、help([object])
查看一个类的所有详细方法
 
>>> help(list)
Help on class list in module __builtin__:

class list(object)
| list() -> new empty list
| list(iterable) -> new list initialized from iterable's items
|
| Methods defined here:
|
| __add__(...)
| x.__add__(y) <==> x+y
|
| __contains__(...)
| x.__contains__(y) <==> y in x
|
| __delitem__(...)
| x.__delitem__(y) <==> del x[y]
|
| __delslice__(...)
| x.__delslice__(i, j) <==> del x[i:j]
|
| Use of negative indices is not supported.
..........

26、hex(x)
获取一个数的十六进制
 
>>> hex(13)
'0xd'

27、id(object)
返回一个对象的内存地址
>>> a = 123
>>> id(a)
1835400816

28、input([prompt])
交互式输入
 
 
29、int(x, base=10)
获取一个数的十进制
>>> int("31")
31

30、isinstance(object, classinfo)
判断对象是否是这个类创建的
 
>>> li = [11,22,33]
>>> isinstance(li,list)
True

31、issubclass(class, classinfo)
查看一个对象是否为子类
 
32、iter(object[, sentinel])
创建一个可迭代的对象
>>> obj = iter([11,22,33,44])
>>> obj
<list_iterator object at 0x000002477DB25198>
>>> for n in obj:
... print(n)
...
11
22
33
44

 
33、len(s)
查看一个对象的长度
 
>>> name = 'lucky'
>>> len(name)
5

34、list([iterable])
创建一个数据类型为列表
>>> li = list([11,22,33,44])
>>> li
[11, 22, 33, 44]

35、locals()
返回当前scripts的局部变量,返回结果为字典格式
>>> def func():
... name="lucky"
... print(locals())
...
>>> func()
{'name': 'lucky'}

 
 
36、map(function, iterable, …)
把可迭代的对象作为函数的值
 
>>> ret = map(lambda x: x + 100, [1, 2, 3, 4, 5])
>>> for n in ret:
... print(n)
...
101
102
103
104
105

37、max(iterable, *[, key, default]) max(arg1, arg2, *args[, key])
获取一个对象中的最大值
 
>>> li = [1, 3, 5, 9 ,3]
>>> max(li)
9

38、min(iterable, *[, key, default])  min(arg1, arg2, *args[, key])
获取一个对象中的最小值
>>> li = list([11,22,33,44])
>>> li = [11,22,33,44]
>>> min(li)
11

39、next(iterator[, default])
 
每次只拿取可迭代对象的一个元素
 
>>> obj = iter([11,22,33,44])
>>> next(obj)
11
>>> next(obj)
22
>>> next(obj)
33
>>> next(obj)
44
>>> next(obj)
# 如果没有可迭代的元素了就会报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

40、oct(x)
获取一个字符串的八进制
>>> oct(13)
'0o15'

41、open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
文件操作的函数,用来做文件操作的
 
 
 
42、ord(c)
把一个字母转换为ASCII对对应表中的数字
 
>>> ord("a")
97
>>> ord("t")
116

43、pow(x, y[, z])
返回一个数的N次方
>>> pow(2, 10)
1024
>>> pow(2, 20)
1048576

 
44、print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)
打印输出
 
 
45、range(start, stop[, step])
生成一个可迭代序列
 
>>> range(10)
range(0, 10)
>>> for n in range(5):
... print(n)
...
0
1
2
3
4

46、reversed(seq)
对一个对象的元素进行反转
>>> li = [1, 2, 3, 4]
>>> reversed(li)
<list_reverseiterator object at 0x000002CF0EF6A940>
>>> for n in reversed(li):
... print(n)
...
4
3
2
1

47、round(number[, ndigits])
四舍五入
>>> round(3.3)
3
>>> round(3.7)
4

48、set([iterable])
创建一个数据类型为集合
>>> varss = set([11,222,333])
>>> type(varss)
<class 'set'>

49、slice(start, stop[, step])
元素的切片操作都是调用的这个方法
 
50、sorted(iterable[, key][, reverse])
为一个对象的元素进行排序
 
>>> li = [ 2, 3, 4, 9, 1, 100]
>>> sorted(li)
[1, 2, 3, 4, 9, 100]

51、sum(iterable[, start])
求和
>>> sum([11,22,33])
66

52、type(object)
查看一个对象的数据类型
 
>>> a = 1
>>> type(a)
<class 'int'>
>>> a = "str"
>>> type(a)
<class 'str'>

53、vars([object])
查看一个对象里面有多少个变量
 
54、zip(*iterables)
联合迭代
>>> li1 = ["k1","k2","k3"]
>>> li2 = ["a","b","c"]
>>> zip(li1,li2)
<zip object at 0x0000026BF1803288>
>>> dic = zip(li1,li2)
>>> for n in dic:
... print(n)
...
('k1', 'a')
('k2', 'b')
('k3', 'c')

55、import(name, globals=None, locals=None, fromlist=(), level=0)
导入模块,把导入的模块作为一个别名。
生成一个六位的随机验证码,且包含数字,数字的位置随机:
# 导入random模块
import random
temp = ""
for i in range(6):
num = random.randrange(0,4)
if num == 3 or num == 1:
rad2 = random.randrange(0,10)
temp = temp + str(rad2)
else:
rad1 = random.randrange(65,91)
c1 = chr(rad1)
temp = temp + c1
print(temp)

服务器主机信息收集

Not see︶ 发表了文章 • 0 个评论 • 602 次浏览 • 2016-08-19 17:24 • 来自相关话题

收集服务器主机信息目的,方便一目了然的去查看,执行dmidecode 感觉比较乱。下面程序可以通过split函数等切片方式进行编写。
目前我想了解的信息是:
1、IP地址(vender)
2、服务器厂商(vender)
3、服务器型号(produ)
4、sn服务器序列号,sn我想显示10个字符
以下程序进行显示:
#!/usr/bin/python

from subprocess import Popen, PIPE

def getIfconfig():
p = Popen(['ifconfig'], stdout=PIPE)
data = p.stdout.read()
return data

def getDmi():
p = Popen(['dmidecode'], stdout=PIPE)
data = p.stdout.read()
return data

def parseData(data):
parsed_data = []
new_line = ''
data = [i for i in data.split('\n') if i]
for line in data:
if line[0].strip():
parsed_data.append(new_line)
new_line = line+'\n'
else:
new_line += line+'\n'
parsed_data.append(new_line)
return [i for i in parsed_data if i]

def parseIfconfig(parsed_data):
dic = {}
parsed_data = [i for i in parsed_data if not i.startswith('lo')]
for lines in parsed_data:
line_list = lines.split('\n')
devname = line_list[0].split()[0]
macaddr = line_list[0].split()[-1]
ipaddr = line_list[1].split()[1].split(':')[1]
break
dic['ip'] = ipaddr
return dic

def parseDmi(parsed_data):
dic = {}
parsed_data = [i for i in parsed_data if i.startswith('System Information')]
parsed_data = [i for i in parsed_data[0].split('\n')[1:] if i]
dmi_dic = dict([i.strip().split(':') for i in parsed_data])
dic['vender'] = dmi_dic['Manufacturer'].strip()
dic['produ'] = dmi_dic['Product Name'].strip()
dic['sn'] = dmi_dic['Serial Number'].strip()[:10]
return dic


if __name__ == '__main__':
data_ip = getIfconfig()
parsed_data_ip = parseData(data_ip)
print parseIfconfig(parsed_data_ip)
data_dmi = getDmi()
parsed_data_dmi = parseData(data_dmi)
print parseDmi(parsed_data_dmi)
[root@Master day5]# ./collect_info_bak.py
{'ip': '192.168.83.169'}
{'vender': 'VMware, Inc.', 'produ': 'VMware Virtual Platform', 'sn': 'VMware-56 '}
接下来我想收集更多的服务器主机信息:
 
1、主机名:hostname
2、IP地址: ip
3、操作系统版本: osver
4、服务器厂商: vender
5、服务器型号: product
6、服务器序列号: sn
7、CPU型号: cpu_model
8、CPU核数: cpu_num
9、内存大小: memory实现方法如下:
#!/usr/bin/python

from subprocess import Popen, PIPE

def getIfconfig():
p = Popen(['ifconfig'], stdout=PIPE)
data = p.stdout.read()
return data

def getDmi():
p = Popen(['dmidecode'], stdout=PIPE)
data = p.stdout.read()
return data

def parseData(data):
parsed_data = []
new_line = ''
data = [i for i in data.split('\n') if i]
for line in data:
if line[0].strip():
parsed_data.append(new_line)
new_line = line+'\n'
else:
new_line += line+'\n'
parsed_data.append(new_line)
return [i for i in parsed_data if i]

def parseIfconfig(parsed_data):
dic = {}
parsed_data = [i for i in parsed_data if not i.startswith('lo')]
for lines in parsed_data:
line_list = lines.split('\n')
devname = line_list[0].split()[0]
macaddr = line_list[0].split()[-1]
ipaddr = line_list[1].split()[1].split(':')[1]
break
dic['ip'] = ipaddr
return dic

def parseDmi(parsed_data):
dic = {}
parsed_data = [i for i in parsed_data if i.startswith('System Information')]
parsed_data = [i for i in parsed_data[0].split('\n')[1:] if i]
dmi_dic = dict([i.strip().split(':') for i in parsed_data])
dic['vender'] = dmi_dic['Manufacturer'].strip()
dic['produ'] = dmi_dic['Product Name'].strip()
dic['sn'] = dmi_dic['Serial Number'].strip()[:10]
return dic

def getHostname(f):
with open(f) as fd:
for line in fd:
if line.startswith('HOSTNAME'):
hostname = line.split('=')[1].strip()
break
return {'hostname':hostname}

def getOSver(f):
with open(f) as fd:
for line in fd:
osver = line.strip()
break
return {'osver':osver}

def getCpu(f):
num = 0
with open(f) as fd:
for line in fd:
if line.startswith('processor'):
num += 1
if line.startswith('model name'):
# print line
cpu_model = line.split(':')[1].split()
cpu_model = cpu_model[0]+' '+cpu_model[-1]
return {'cpu_num':num, 'cpu_model':cpu_model}

def getMemory(f):
with open(f) as fd:
for line in fd:
if line.startswith('MemTotal'):
mem = int(line.split()[1].strip())
break
mem = "%s" % int(mem/1024.0)+'M'
return {'memory':mem}


if __name__ == '__main__':
dic = {}
data_ip = getIfconfig()
parsed_data_ip = parseData(data_ip)
ip = parseIfconfig(parsed_data_ip)
data_dmi = getDmi()
parsed_data_dmi = parseData(data_dmi)
dmi = parseDmi(parsed_data_dmi)
hostname = getHostname('/etc/sysconfig/network')
osver = getOSver('/etc/issue')
cpu = getCpu('/proc/cpuinfo')
mem = getMemory('/proc/meminfo')
dic.update(ip)
dic.update(dmi)
dic.update(hostname)
dic.update(osver)
dic.update(cpu)
dic.update(mem)
print dic这样以后整理资产的时候可以清楚的了解到每台机器的情况了 查看全部
收集服务器主机信息目的,方便一目了然的去查看,执行dmidecode 感觉比较乱。下面程序可以通过split函数等切片方式进行编写。
目前我想了解的信息是:
1、IP地址(vender)
2、服务器厂商(vender)
3、服务器型号(produ)
4、sn服务器序列号,sn我想显示10个字符
以下程序进行显示:
#!/usr/bin/python

from subprocess import Popen, PIPE

def getIfconfig():
p = Popen(['ifconfig'], stdout=PIPE)
data = p.stdout.read()
return data

def getDmi():
p = Popen(['dmidecode'], stdout=PIPE)
data = p.stdout.read()
return data

def parseData(data):
parsed_data = []
new_line = ''
data = [i for i in data.split('\n') if i]
for line in data:
if line[0].strip():
parsed_data.append(new_line)
new_line = line+'\n'
else:
new_line += line+'\n'
parsed_data.append(new_line)
return [i for i in parsed_data if i]

def parseIfconfig(parsed_data):
dic = {}
parsed_data = [i for i in parsed_data if not i.startswith('lo')]
for lines in parsed_data:
line_list = lines.split('\n')
devname = line_list[0].split()[0]
macaddr = line_list[0].split()[-1]
ipaddr = line_list[1].split()[1].split(':')[1]
break
dic['ip'] = ipaddr
return dic

def parseDmi(parsed_data):
dic = {}
parsed_data = [i for i in parsed_data if i.startswith('System Information')]
parsed_data = [i for i in parsed_data[0].split('\n')[1:] if i]
dmi_dic = dict([i.strip().split(':') for i in parsed_data])
dic['vender'] = dmi_dic['Manufacturer'].strip()
dic['produ'] = dmi_dic['Product Name'].strip()
dic['sn'] = dmi_dic['Serial Number'].strip()[:10]
return dic


if __name__ == '__main__':
data_ip = getIfconfig()
parsed_data_ip = parseData(data_ip)
print parseIfconfig(parsed_data_ip)
data_dmi = getDmi()
parsed_data_dmi = parseData(data_dmi)
print parseDmi(parsed_data_dmi)

[root@Master day5]# ./collect_info_bak.py 
{'ip': '192.168.83.169'}
{'vender': 'VMware, Inc.', 'produ': 'VMware Virtual Platform', 'sn': 'VMware-56 '}

接下来我想收集更多的服务器主机信息:
 
1、主机名:hostname
2、IP地址: ip
3、操作系统版本: osver
4、服务器厂商: vender
5、服务器型号: product
6、服务器序列号: sn
7、CPU型号: cpu_model
8、CPU核数: cpu_num
9、内存大小: memory
实现方法如下:
#!/usr/bin/python

from subprocess import Popen, PIPE

def getIfconfig():
p = Popen(['ifconfig'], stdout=PIPE)
data = p.stdout.read()
return data

def getDmi():
p = Popen(['dmidecode'], stdout=PIPE)
data = p.stdout.read()
return data

def parseData(data):
parsed_data = []
new_line = ''
data = [i for i in data.split('\n') if i]
for line in data:
if line[0].strip():
parsed_data.append(new_line)
new_line = line+'\n'
else:
new_line += line+'\n'
parsed_data.append(new_line)
return [i for i in parsed_data if i]

def parseIfconfig(parsed_data):
dic = {}
parsed_data = [i for i in parsed_data if not i.startswith('lo')]
for lines in parsed_data:
line_list = lines.split('\n')
devname = line_list[0].split()[0]
macaddr = line_list[0].split()[-1]
ipaddr = line_list[1].split()[1].split(':')[1]
break
dic['ip'] = ipaddr
return dic

def parseDmi(parsed_data):
dic = {}
parsed_data = [i for i in parsed_data if i.startswith('System Information')]
parsed_data = [i for i in parsed_data[0].split('\n')[1:] if i]
dmi_dic = dict([i.strip().split(':') for i in parsed_data])
dic['vender'] = dmi_dic['Manufacturer'].strip()
dic['produ'] = dmi_dic['Product Name'].strip()
dic['sn'] = dmi_dic['Serial Number'].strip()[:10]
return dic

def getHostname(f):
with open(f) as fd:
for line in fd:
if line.startswith('HOSTNAME'):
hostname = line.split('=')[1].strip()
break
return {'hostname':hostname}

def getOSver(f):
with open(f) as fd:
for line in fd:
osver = line.strip()
break
return {'osver':osver}

def getCpu(f):
num = 0
with open(f) as fd:
for line in fd:
if line.startswith('processor'):
num += 1
if line.startswith('model name'):
# print line
cpu_model = line.split(':')[1].split()
cpu_model = cpu_model[0]+' '+cpu_model[-1]
return {'cpu_num':num, 'cpu_model':cpu_model}

def getMemory(f):
with open(f) as fd:
for line in fd:
if line.startswith('MemTotal'):
mem = int(line.split()[1].strip())
break
mem = "%s" % int(mem/1024.0)+'M'
return {'memory':mem}


if __name__ == '__main__':
dic = {}
data_ip = getIfconfig()
parsed_data_ip = parseData(data_ip)
ip = parseIfconfig(parsed_data_ip)
data_dmi = getDmi()
parsed_data_dmi = parseData(data_dmi)
dmi = parseDmi(parsed_data_dmi)
hostname = getHostname('/etc/sysconfig/network')
osver = getOSver('/etc/issue')
cpu = getCpu('/proc/cpuinfo')
mem = getMemory('/proc/meminfo')
dic.update(ip)
dic.update(dmi)
dic.update(hostname)
dic.update(osver)
dic.update(cpu)
dic.update(mem)
print dic
这样以后整理资产的时候可以清楚的了解到每台机器的情况了