Python学习笔记3:Python常见模块的用法

这一部分是Python方面的一些学习笔记,用于记录自己学习Python的过程,同时也是对自己Python这块知识的一个梳理,后期也可用于Python复习。

Python学习的第三篇,介绍Python常见模块的用法,其中包括os模块、matplotlab模块等。

Python的系统模块包括sys, os, glob, socket, threading, _thread, queue, time, timeit, subprocess, multiprocessing, signal, select, shutil, tempfile等。大多数系统级接口集中在:sys和os两个模块。

sys模块

sys模块包括了一组非常实用的服务,内含很多函数方法和变量,用来处理Python运行时配置以及资源,从而可以与前当程序之外的系统环境交互,如:Python解释器。与os模块相比,其更多的在于针对系统环境的交互,而os则操作文件目录。

导入sys模块

首先,打开终端模拟器进入Python解释器或者打开IDE编辑器创建一个新的.py后缀名的Python程序文件。
下面,以解释器中的操作举例:

       
      
      
      
1
2
       
      
      
      
import sys
dir(sys) #dir()方法查看模块中可用的方法

`
注意:如果是在编辑器,一定要注意要事先声明代码的编码方式,否则中文会乱码。

sys模块常见函数

  • sys.argv: 命令行参数,包括脚本名称,实现从程序外部向程序传递参数
  • sys.exit([arg]): 程序中间的退出,arg=0为正常退出
  • sys.path: 查找模块所在目录的目录名列表
  • sys.modules:映射模块名字到载入模块的字典
  • sys.platform: 获取当前系统平台
  • sys.stdin:标准输入流-一个类文件(file-like)对象
  • sys.stdout:标准输出流-一个类文件对象
  • sys.stderr:标准错误流-一个类文件对象
  • sys.getdefaultencoding(): 获取系统当前编码,一般默认为ascii。
  • sys.setdefaultencoding(): 设置系统默认编码,需要reload(sys)才能查询看到
  • sys.getfilesystemencoding(): 获取文件系统使用编码方式,Windows下返回’mbcs’,mac下返回’utf-8’

sys模块常见函数

sys.argv

sys.argv是命令行参数,包括脚本名称,它的功能可以实现从程序外部向程序传递参数。那么这个过程是如何实现的呢?假设有一个名为test.py的文件,则可以通过import sysprint sys.argv[number]两句来实现。number=0为这个脚本的名字,1,2,…则为命令行下传递的参数。

如test.py脚本内容如下:

       
      
      
      
1
2
3
4
5
6
       
      
      
      
import sys
print sys.argv[ 0]
print sys.argv[ 1]
print sys.argv[ 2]
print sys.argv[ 3]

那么要实现参数传递即可采用>>>python test.py arg1 arg2 arg3实现。下文会结合sys.path给出一个示例。上述命令的输出结果为:

       
      
      
      
1
2
3
4
       
      
      
      
test.py
arg1
arg2
arg3

sys.exit([arg])

执行至主程序的末尾时,解释器会自动退出。但如果需要中途退出程序,可以调用sys.exit()函数来实现。它带有一个可选的整数参数返回给调用它的程序。这意味着你可以在主程序中捕获对sys.exit()的调用。(0为正常退出,其他为不正常,可抛异常事件供捕获)

sys.exit()函数运行示例如下:

       
      
      
      
1
2
3
4
5
6
7
8
       
      
      
      
import sys
print "hello"
try:
sys.exit( 1)
except SystemExit: # 捕获退出的异常
pass # 捕获后不做任何操作
print "there"

输出结果为:

       
      
      
      
1
2
       
      
      
      
hello
there

还可以获取发生的异常类型(需要进入异常处理进程),如以下示例:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
       
      
      
      
def (value):
print value # 打印异常类型
sys.exit( 0) # 正常退出
print 'Hello'
try:
sys.exit( 1)
except SystemExit,value: # 捕获退出的异常与其value值
exitfunc(value) # 调用函数,打印捕获的异常类型
print 'end' # 如果function里没有 sys.exit(0)命令,这句仍会被执行。

上述代码输出结果见下:

       
      
      
      
1
2
3
4
5
       
      
      
      
Hello
1
An exception has occurred, use %tb to see the full trackback.
SystemExit: 0

执行%tb命令后发现其追踪了sys.exit(0)这句异常,但并没有追踪sys.exit(1)这句异常,实际上sys.exit(1)这个并不是异常退出原因。try...except...语句为异常处理语句,一般而言执行完try命令后会在except语句中查询符合的类型,语句会顺序执行,并不是如sys.exit(0)一样直接退出了。

有另一种捕获sys.exit调用的方法,代码如下:

       
      
      
      
1
2
3
4
5
6
7
       
      
      
      
def ():
print "world"
sys.exitfunc = exitfunc # 设置捕获时调用的函数
print "hello"
sys.exit( 1) # 退出自动调用exitfunc()后,程序依然退出了
print "there" # 不会被 print

输出结果为:

       
      
      
      
1
2
3
4
       
      
      
      
hello
world
SystemExit: 1

这种方式的退出异常类型为代码中显示的1,因为其异常直接导致了进程的推出。

sys.path

sys.path的功能是获取指定模块搜索路径的字符串集合,可以将写好的模块放在得到的某个路径下,就可以在程序中import时正确找到。

示例:

       
      
      
      
1
2
3
       
      
      
      
import sys
sys.path
[ '', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client']

可以采用sys.path.append("自定义模块路径")增加模块搜索路径(也可以用sys.path.insert进行列表插入)。以上列出的模块目录,在python执行import module_name时,会依次从上述列出的路径来搜索对应的模块。如有需要手动添加模块,可放入对应的路径中,如无必要建议不要手动添加路径。``代表当前文件目录。

上问提到的sys.argv参数传递示例如下:

输入:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
       
      
      
      
#!/usr/bin/python
# Filename: using_sys.py
import sys
print 'The command line arguments are:'
for i in sys.argv:
print i
print 'nnThe PYTHONPATH is', sys.path, 'n'

输出:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
       
      
      
      
python using_sys.py we are arguments
The command line arguments are:
using_sys.py
we
are
arguments
The PYTHONPATH is [ '/home/swaroop/byte/code', '/usr/lib/python23.zip',
'/usr/lib/python2.3', '/usr/lib/python2.3/plat-linux2',
'/usr/lib/python2.3/lib-tk', '/usr/lib/python2.3/lib-dynload',
'/usr/lib/python2.3/site-packages', '/usr/lib/python2.3/site-packages/gtk-2.0']

sys.modules

sys.modules是一个全局字典,该字典是python启动后就加载在内存中。每当导入新的模块时,sys.modules将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快了程序运行的速度。它拥有字典所拥有的一切方法。

示例:

       
      
      
      
1
2
3
4
5
       
      
      
      
import sys
print sys.modules.keys() # 列出所有的模块名
print sys.modules[ 'os'] # 列出指定模块如os模块所在路径
print sys.modules.values() # 列出所有模块所在路径(含values值?应该没必要了解)

uiltin_module_names列表包含了Python解释器中所有内建模块的名称。代码如下:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
       
      
      
      
def dump(module):
print module, "=>",
if module in sys.builtin_module_names: #查找内建模块是否存在
print ""
else:
module = _ _import_ _(module) #非内建模块输出模块路径
print module._ _file_ _
dump( "os")
dump( "sys")
dump( "string")
dump( "strop")
dump( "zlib")

输出(示例,以实际安装情况为准):

       
      
      
      
1
2
3
4
5
       
      
      
      
os => C:pythonlibos.pyc
sys =>
string => C:pythonlibstring.pyc
strop =>
zlib => C:pythonzlib.pyd

sys.platform

sys.platform语句用于查看当前平台,如win32、linux2等。

       
      
      
      
1
2
       
      
      
      
>>> print sys.platform
win32 #linux2

sys.stdin/sys.stdout/sys.stderr

sys.stdin/sys.stdout/sys.stderr变量包含与标准I/O流对应的流对象。如果需要更好地控制输出,而print不能满足你的要求,它们就是你所需要的。你也可以替换它们,这时候你就可以重定向输出和输入到其它设备( device ),或者以非标准的方式处理它们。

我们平时的输入输出方式通过input/raw_input/print实现,即

       
      
      
      
1
2
       
      
      
      
print 'Hello World!'
print 'Hi, %s!' % raw_input( 'Please enter your name:')

上述中,键盘键入的信息则为标准输入,屏幕输出的结果则为标准输出。而上述的例子,与下文采用sys.stdin/sys.stdout的结果是一致的。

       
      
      
      
1
2
3
4
5
6
7
8
9
10
       
      
      
      
import sys
sys.stdout.write( 'Hello World!')
import sys
print 'Please enter your name:',
name=sys.stdin.readline()[: -1]
print 'Hi, %s!' % name

输入for f in (sys.stdin, sys.stdout, sys.stderr): print f可查看属性信息。

       
      
      
      
1
2
3
       
      
      
      
'', mode 'r' at 892210>
'', mode 'w' at 892270>
'', mode 'w at 8922d0>

注:通过IPython输出结果与上述有所出入,但上述要表述的信息正确。

stdin/stdout/stderr在Python中都是文件属性的对象,在Python启动时自动与Shell 环境中的标准输入/输出/出错关联。与标准输出print和标准出错所不同的是,stdin/stdout/stderr三者不具备自动回车功能,而标准输入输出则默认自动加了回车。stdin只读,stdout和stderr只写。

使用sys重定向输出

代码如下:

       
      
      
      
1
2
3
4
5
6
7
       
      
      
      
print 'Dive in' # 标准输出
saveout = sys.stdout # 终在重定向前保存stdout,这样的话之后你还可以将其设回正常
fsock = open( 'out.log', 'w') # 打开一个新文件用于写入。如果文件不存在,将会被创建。如果文件存在,将被覆盖。
sys.stdout = fsock # 所有后续的输出都会被重定向到刚才打开的新文件上。
print 'This message will be logged instead of displayed' # 这样只会将输出结果“打印”到日志文件中;屏幕上不会看到输出
sys.stdout = saveout # 在我们将 stdout 搞乱之前,让我们把它设回原来的方式。
fsock.close() # 关闭日志文件。

(下述sys重定向部分仅做一个拓展)

重定向错误信息

fsock = open(‘error.log’, ‘w’) # 打开你要存储调试信息的日志文件。
sys.stderr = fsock # 将新打开的日志文件的文件对象赋值给stderr以重定向标准错误。
raise Exception, ‘this error will be logged’ # 引发一个异常,没有在屏幕上打印出任何东西,所有正常的跟踪信息已经写进error.log
还要注意你既没有显式关闭日志文件,也没有将 stderr 设回最初的值。
这样挺好,因为一旦程序崩溃 (由于引发的异常),Python 将替我们清理并关闭文件

打印到 stderr

向标准错误写入错误信息是很常见的,所以有一种较快的语法可以立刻导出信息
代码如下:

       
      
      
      
1
2
3
4
5
       
      
      
      
>>> print 'entering function'
entering function
>>> import sys
>>> print >> sys.stderr, 'entering function'
entering function

print 语句的快捷语法可以用于写入任何打开的文件 (或者是类文件对象)。
在这里,你可以将单个print语句重定向到stderr而且不用影响后面的print语句。

更多详见:sys模块官网文档

os模块

Python 的 os 模块封装了常见的文件和目录操作,本文只列出部分常用的方法,更多的方法可以查看官方文档。

常见用法一

  • os.mkdir(name) 创建目录
  • os.rmdir(name) 删除目录
  • os.rename(name) 重命名
  • os.remove(file) 删除文件
  • os.getcwd() 获取当前工作路径
  • os.walk 遍历目录
  • os.path.join(path,name) 连接目录与文件名
  • os.path.split(name) 分割文件名与目录
  • os.path.abspath(name) 获取绝对路径
  • os.path.dirname(path) 获取路径
  • os.path.basename(path) 获取文件名或文件夹名
  • os.path.splitext() 分离文件名与扩展名
  • os.path.isfile() 判断给出的路径是否是一个文件
  • os.path.isdir() 判断给出的路径是否是一个目录
  • os.urandom(n):返回n字节的加密强随机数据

以下面的目录结构为参考,工作目录为 /Users/ethan/coding/python,展示os模块用法

Users/ethan
└── coding
└── python
├── hello.py - 文件
└── web - 目录

  • os.path.abspath:获取文件或目录的绝对路径

             
            
            
            
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
             
            
            
            
    >>> pwd
    /Users/ethan/coding/python
    >>> python
    >>> import os # 记得导入 os 模块
    >>> os.path.abspath( 'hello.py')
    '/Users/ethan/coding/python/hello.py'
    >>> os.path.abspath( 'web')
    '/Users/ethan/coding/python/web'
    >>> os.path.abspath( '.') # 当前目录的绝对路径
    '/Users/ethan/coding/python'
  • os.path.dirname:获取文件或文件夹的路径

             
            
            
            
    1
    2
    3
    4
    5
    6
             
            
            
            
    >>> os.path.dirname( '/Users/ethan/coding/python/hello.py')
    '/Users/ethan/coding/python'
    >>> os.path.dirname( '/Users/ethan/coding/python/')
    '/Users/ethan/coding/python'
    >>> os.path.dirname( '/Users/ethan/coding/python')
    '/Users/ethan/coding'
  • os.path.basename:获取文件名或文件夹名

             
            
            
            
    1
    2
    3
    4
    5
    6
             
            
            
            
    >>> os.path.basename( '/Users/ethan/coding/python/hello.py')
    'hello.py'
    >>> os.path.basename( '/Users/ethan/coding/python/')
    ''
    >>> os.path.basename( '/Users/ethan/coding/python')
    'python'
  • os.path.splitext:分离文件名与扩展名

             
            
            
            
    1
    2
    3
    4
    5
    6
             
            
            
            
    >>> os.path.splitext( '/Users/ethan/coding/python/hello.py')
    ( '/Users/ethan/coding/python/hello', '.py')
    >>> os.path.splitext( '/Users/ethan/coding/python')
    ( '/Users/ethan/coding/python', '')
    >>> os.path.splitext( '/Users/ethan/coding/python/')
    ( '/Users/ethan/coding/python/', '')
  • os.path.split:分离目录与文件名

             
            
            
            
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
             
            
            
            
    >>> os.path.split( '/Users/ethan/coding/python/hello.py')
    ( '/Users/ethan/coding/python', 'hello.py')
    >>> os.path.split( '/Users/ethan/coding/python/')
    ( '/Users/ethan/coding/python', '')
    >>> os.path.split( '/Users/ethan/coding/python')
    ( '/Users/ethan/coding', 'python')
    os.path.isfile/os.path.isdir
    >>> os.path.isfile( '/Users/ethan/coding/python/hello.py')
    True
    >>> os.path.isdir( '/Users/ethan/coding/python/')
    True
    >>> os.path.isdir( '/Users/ethan/coding/python')
    True
    >>> os.path.isdir( '/Users/ethan/coding/python/hello.py')
    False
  • os.walk
    os.walk 是遍历目录常用的模块,它返回一个包含 3 个元素的元祖:(dirpath, dirnames, filenames)。dirpath 是以 string 字符串形式返回该目录下所有的绝对路径;dirnames 是以列表 list 形式返回每一个绝对路径下的文件夹名字;filesnames 是以列表 list 形式返回该路径下所有文件名字。

             
            
            
            
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
             
            
            
            
    >>> for root, dirs, files in os.walk( '/Users/ethan/coding'):
    ... print root
    ... print dirs
    ... print files
    ...
    /Users/ethan/coding
    [ 'python']
    []
    /Users/ethan/coding/python
    [ 'web2']
    [ 'hello.py']
    /Users/ethan/coding/python/web2
    []
    []

常见用法二

其他较常见函数列表如下:

  • os.sep:取代操作系统特定的路径分隔符
  • os.name:指示你正在使用的工作平台。比如对于Windows,它是’nt’,而对于Linux/Unix用户,它是’posix’。
  • os.getenv()和os.putenv:分别用来读取和设置环境变量
  • os.listdir(name):返回指定目录下的所有文件和目录名
  • os.stat(file):获得文件属性
  • os.chmod(file):修改文件权限和时间戳
  • os.removedirs(r“c:python”):删除多个目录
  • os.environ:对环境变量进行映射
  • os.system():运行shell命令
  • os.exit():终止当前进程
  • os.linesep:给出当前平台的行终止符。例如,Windows使用’rn’,Linux使用’n’而Mac使用’r’
  • os.curdir:返回当前目录(’.’)
  • os.chdir(dirname):改变工作目录到dirname
  • os.pathsep:分隔路径的分隔符
  • os.path.existe():检验给出的路径是否真的存在
  • os.path.exists(name):判断是否存在文件或目录name
  • os.path.getsize(name):或得文件大小,如果name是目录返回0L
  • os.path.isabs():判断是否为绝对路径
  • os.path.normpath(path):规范path字符串形式

其他

shutil.copyfile("oldfile","newfile")       

复制文件,oldfile和newfile都只能是文件

shutil.copy("oldfile","newfile")            

oldfile只能是文件夹,newfile可以是文件,也可以是目标目录

shutil.copytree("olddir","newdir")        

复制文件夹.olddir和newdir都只能是目录,且newdir必须不存在

shutil.move("oldpos","newpos")   

移动文件(目录)

os.rmdir("dir")

只能删除空目录

shutil.rmtree("dir")

空目录、有内容的目录都可以删

fileinput

典型用法

       
      
      
      
1
2
3
       
      
      
      
import fileinput
for line in fileinput.input():
process(line)

常用函数

fileinput.input() #返回能够用于for循环遍历的对象
fileinput.filename() #返回当前文件的名称
fileinput.lineno() #返回当前已经读取的行的数量(或者序号)
fileinput.filelineno() #返回当前读取的行的行号
fileinput.isfirstline() #检查当前行是否是文件的第一行
fileinput.isstdin() #判断最后一行是否从stdin中读取
fileinput.close() #关闭队列

常见例子

例子01: 利用fileinput读取一个文件所有行

       
      
      
      
1
2
3
4
5
6
7
8
       
      
      
      
>>> import fileinput
>>> for line in fileinput.input( 'data.txt'):
print line,
#输出结果
Python
Java
C/C++
Shell

命令行方式:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
       
      
      
      
#test.py
import fileinput
for line in fileinput.input():
print fileinput.filename(), '|', 'Line Number:',fileinput.lineno(), '|: ',line
c:>python test.py data.txt
data.txt | Line Number: 1 |: Python
data.txt | Line Number: 2 |: Java
data.txt | Line Number: 3 |: C/C++
data.txt | Line Number: 4 |: Shell

例子02: 利用fileinput对多文件操作,并原地修改内容

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
       
      
      
      
#test.py
#---样本文件---
c:Python27>type 1.txt
first
second
c:Python27>type 2.txt
third
fourth
#---样本文件---
import fileinput
def process(line):
return line.rstrip() + ' line'
for line in fileinput.input([ '1.txt', '2.txt'],inplace= 1):
print process(line)
#---结果输出---
c:Python27>type 1.txt
first line
second line
c:Python27>type 2.txt
third line
fourth line
#---结果输出---

命令行方式:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
       
      
      
      
#test.py
import fileinput
def process(line):
return line.rstrip() + ' line'
for line in fileinput.input(inplace = True):
print process(line)
#执行命令
c:Python27>python test.py 1.txt 2.txt

例子03: 利用fileinput实现文件内容替换,并将原文件作备份

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
       
      
      
      
#样本文件:
#data.txt
Python
Java
C/C++
Shell
#FileName: test.py
import fileinput
for line in fileinput.input( 'data.txt',backup= '.bak',inplace= 1):
print line.rstrip().replace( 'Python', 'Perl') #或者print line.replace('Python','Perl'),
#最后结果:
#data.txt
Python
Java
C/C++
Shell
#并生成:
#data.txt.bak文件
#其效果等同于下面的方式
import fileinput
for line in fileinput.input():
print 'Tag:',line,
#---测试结果:
d:>python Learn.py < data.txt > data_out.txt

例子04: 利用fileinput将CRLF文件转为LF

       
      
      
      
1
2
3
4
5
6
7
8
       
      
      
      
import fileinput
import sys
for line in fileinput.input(inplace= True):
#将Windows/DOS格式下的文本文件转为Linux的文件
if line[ -2:] == "rn":
line = line + "n"
sys.stdout.write(line)

例子05: 利用fileinput对文件简单处理

例子06: 利用fileinput批处理文件

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
       
      
      
      
#---测试文件: test.txt test1.txt test2.txt test3.txt---
#---脚本文件: test.py---
import fileinput
import glob
for line in fileinput.input(glob.glob( "test*.txt")):
if fileinput.isfirstline():
print '-'* 20, 'Reading %s...' % fileinput.filename(), '-'* 20
print str(fileinput.lineno()) + ': ' + line.upper(),
#---输出结果:
>>>
-------------------- Reading test.txt... --------------------
1: AAAAA
2: BBBBB
3: CCCCC
4: DDDDD
5: FFFFF
-------------------- Reading test1.txt... --------------------
6: FIRST LINE
7: SECOND LINE
-------------------- Reading test2.txt... --------------------
8: THIRD LINE
9: FOURTH LINE
-------------------- Reading test3.txt... --------------------
10: THIS IS LINE 1
11: THIS IS LINE 2
12: THIS IS LINE 3
13: THIS IS LINE 4

例子07: 利用fileinput及re做日志分析: 提取所有含日期的行

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
       
      
      
      
#--样本文件--
aaa
1970-01-01 13:45:30 Error: **** Due to System Disk spacke not enough...
bbb
1970-01-02 10:20:30 Error: **** Due to System Out of Memory...
ccc
#---测试脚本---
import re
import fileinput
import sys
pattern = 'd{4}-d{2}-d{2} d{2}:d{2}:d{2}'
for line in fileinput.input('error.log',backup='.bak',inplace=1):
if re.search(pattern,line):
sys.stdout.write("=> ")
sys.stdout.write(line)
#---测试结果---
=> 1970-01-01 13:45:30 Error: **** Due to System Disk spacke not enough...
=> 1970-01-02 10:20:30 Error: **** Due to System Out of Memory...

例子08: 利用fileinput及re做分析: 提取符合条件的电话号码

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
       
      
      
      
#---样本文件: phone.txt---
010 -110 -12345
800 -333 -1234
010 -99999999
05718888888
021 -88888888
#---测试脚本: test.py---
import re
import fileinput
pattern = '[010|021]-d{8}' #提取区号为010或021电话号码,格式:010-12345678
for line in fileinput.input( 'phone.txt'):
if re.search(pattern,line):
print '=' * 50
print 'Filename:'+ fileinput.filename()+ ' | Line Number:'+str(fileinput.lineno())+ ' | '+line,
#---输出结果:---
>>>
==================================================
Filename:phone.txt | Line Number: 3 | 010 -99999999
==================================================
Filename:phone.txt | Line Number: 5 | 021 -88888888
>>>

例子09: 利用fileinput实现类似于grep的功能

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
       
      
      
      
import sys
import re
import fileinput
pattern= re.compile(sys.argv[ 1])
for line in fileinput.input(sys.argv[ 2]):
if pattern.match(line):
print fileinput.filename(), fileinput.filelineno(), line
$ ./test.py import.*re *.py
#查找所有py文件中,含import re字样的
addressBook.py 2 import re
addressBook1.py 10 import re
addressBook2.py 18 import re
test.py 238 import re

例子10: 利用fileinput做正则替换

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
       
      
      
      
#---测试样本: input.txt
* [Learning Python](#author:Mark Lutz)
#---测试脚本: test.py
import fileinput
import re
for line in fileinput.input():
line = re.sub(r'*
(.∗)
#(.*)', r'

1

', line.rstrip())
print(line)
#---输出结果:
c:Python27>python test.py input.txt

Learning Python

例子11: 利用fileinput做正则替换,不同字模块之间的替换
#---测试样本:test.txt
[@!$First]&[*%-Second]&[Third]
#---测试脚本:test.py
import re
import fileinput
regex = re.compile(r'^([^&]*)(&)([^&]*)(&)([^&]*)')
#整行以&分割,要实现[@!$First]与[*%-Second]互换
for line in fileinput.input('test.txt',inplace=1,backup='.bak'):
print regex.sub(r'32145',line),
#---输出结果:
[*%-Second]&[@!$First]&[Third]
例子12: 利用fileinput根据argv命令行输入做替换
#---样本数据: host.txt
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
127.0.0.1 localhost
192.168.100.2 www.test2.com
192.168.100.3 www.test3.com
192.168.100.4 www.test4.com
#---测试脚本: test.py
import sys
import fileinput
source = sys.argv[1]
target = sys.argv[2]
files = sys.argv[3:]
for line in fileinput.input(files,backup='.bak',openhook=fileinput.hook_encoded("gb2312")):
#对打开的文件执行中文字符集编码
line = line.rstrip().replace(source,target)
print line
#---输出结果:
c:>python test.py 192.168.100 127.0.0 host.txt
#将host文件中,所有192.168.100转换为:127.0.0
127.0.0.1 localhost
127.0.0.2 www.test2.com
127.0.0.3 www.test3.com
127.0.0.4 www.test4.com

集合(set)类型

python的set和其他语言类似, 是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素. 集合对象还支持union(联合), intersection(交), difference(差)和sysmmetric difference(对称差集)等数学运算。注:set不需要通过import引入。

sets 支持 x in set, len(set),和 for x in set。作为一个无序的集合,sets不记录元素位置或者插入点。因此,sets不支持 indexing, slicing, 或其它类序列(sequence-like)的操作。

set示例

       
      
      
      
1
2
3
4
5
6
7
       
      
      
      
>>> a = set([ 1, 2, 3]) #创建一个数值集合set
>>> b = set([ 2, 3, 4])
>>> print a,b
set([ 1, 2, 3]), set([ 2, 3, 4])
>>> x = set( 'spam') # 创建一个唯一字符集合set
>>> print x
set([ 'a', 'p', 's', 'm'])

集合set与列表和元组不同,集合是无序的,也无法通过数字进行索引。同时,集合中的元素不能重复。利用集合set元素不重复这个特性,可以去除list列表中的重复值。

       
      
      
      
1
2
3
4
5
6
7
8
       
      
      
      
>>> a = [ 11, 22, 33, 44, 11, 22]
>>> b = set(a)
>>> b
set([ 33, 11, 44, 22])
>>> c = [i for i in b]
>>> c
[ 33, 11, 44, 22]
# 此法也可用于list和set之间的互换

基本操作

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
       
      
      
      
a = t | s # t 和 s的并集
b = t & s # t 和 s的交集
c = t – s # 求差集(项在t中,但不在s中)
d = t ^ s # 对称差集(t和s中不重复项)
t.add( 'x') # 添加一项
s.update([ 10, 37, 42]) # 在s中添加多项
t.remove( 'H') # 移除其中一项
len(s) # set 的长度
x in s # 测试 x 是否是 s 的成员
x not in s # 测试 x 是否不是 s 的成员
s.issubset(t)
s <= t
# 测试是否 s 中的每一个元素都在 t 中
s.issuperset(t)
s >= t
# 测试是否 t 中的每一个元素都在 s 中
s.union(t)
s | t
# 返回一个新的 set 包含 s 和 t 中的每一个元素
s.intersection(t)
s & t
# 返回一个新的 set 包含 s 和 t 中的公共元素
s.difference(t)
s - t
# 返回一个新的 set 包含 s 中有但是 t 中没有的元素
s.symmetric_difference(t)
s ^ t
# 返回一个新的 set 包含 s 和 t 中不重复的元素
s.copy()
# 返回 set “s”的一个浅复制
# 注 s.copy() is s: False
s.update(t)
s |= t
# 返回增加了 set “t”中元素后的 set “s”
s.intersection_update(t)
s &= t
# 返回只保留含有 set “t”中元素的 set “s”
s.difference_update(t)
s -= t
# 返回删除了 set “t”中含有的元素后的 set “s”
s.symmetric_difference_update(t)
s ^= t
# 返回含有 set “t”或者 set “s”中有而不是两者都有的元素的 set “s”
s.add(x)
# 向 set “s”中增加元素 x
s.remove(x)
# 从 set “s”中删除元素 x, 如果不存在则引发 KeyError
s.discard(x)
# 如果在 set “s”中存在元素 x, 则删除
s.pop()
# 删除并且返回 set “s”中的一个不确定的元素, 如果为空则引发 KeyError
s.clear()
# 删除 set “s”中的所有元素

参考: Python集合(set)类型的操作

range和xrange

range和xrange都不用引入import,都可直接使用。

range函数用法:range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列。

range示例:

       
      
      
      
1
2
3
4
5
6
       
      
      
      
>>> range( 5)
[ 0, 1, 2, 3, 4]
>>> range( 1, 5)
[ 1, 2, 3, 4]
>>> range( 0, 6, 2)
[ 0, 2, 4]

xrange用法和range完全相同,所不同的是生成的不是一个数组,而是一个生成器。

       
      
      
      
1
2
3
4
5
6
7
       
      
      
      
>>> y = xrange( 5)
>>> print y
xrange(y)
>>> print type(y)
'xrange'>
>>> list(y)
[ 0, 1, 2, 3, 4]

由上面的示例可以知道:要生成很大的数字序列的时候,用xrange会比range性能优很多,因为不需要一上来就开辟一块很大的内存空间.

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
       
      
      
      
#循环中的用法
for i in range( 0, 100):
print i
for i in xrange( 0, 100):
print i
#以上这两个输出的结果都是一样的,实际上有很多不同,range会直接生成一个list对象:
a = range( 0, 100)
print type(a)
print a
print a[ 0], a[ 1]
#输出结果
'list'>
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
0 1
#而xrange则不会直接生成一个list,而是每次调用返回其中的一个值
a = xrange( 0, 100)
print type(a)
print a
print a[ 0], a[ 1]
#输出结果:
'xrange'>
xrange( 100)
0 1

time

在Python中,与时间处理有关的模块就包括:time,datetime以及calendar

在开始之前,首先要说明这几点:

  1. 在Python中,通常有这几种方式来表示时间:1)时间戳timestamp; 2)格式化的时间字符串; 3)元组(struct_time,共九个元素)。由于Python的time模块实现主要调用C库,所以各个平台可能有所不同。
  2. UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。
  3. 时间戳(timestamp)的方式:通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。返回时间戳方式的函数主要有time(),clock()等。
  4. 元组(struct_time)方式:struct_time元组共有9个元素,返回struct_time的函数主要有全球统一时间gmtime(),localtime(),strptime()。下面列出这种方式元组中的几个元素:

元组的九个元素如下表所示:

索引(Index) 属性(Attribute) 值(Values)
0 tm_year(年) 比如2011
1 tm_mon(月) 1 - 12
2 tm_mday(日) 1 - 31
3 tm_hour(时) 0 - 23
4 tm_min(分) 0 - 59
5 tm_sec(秒) 0 - 61(包含闰秒和双闰秒)
6 tm_wday(weekday) 0 - 6(0表示周一)
7 tm_yday(一年中的第几天) 1 - 366
8 tm_isdst(是否是夏令时) 默认为-1,0,1

常用函数

time.localtime([secs])

将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。

       
      
      
      
1
2
3
4
       
      
      
      
>>> time.localtime()
time.struct_time(tm_year= 2011, tm_mon= 5, tm_mday= 5, tm_hour= 14, tm_min= 14, tm_sec= 50, tm_wday= 3, tm_yday= 125, tm_isdst= 0)
>>> time.localtime( 1304575584.1361799)
time.struct_time(tm_year= 2011, tm_mon= 5, tm_mday= 5, tm_hour= 14, tm_min= 6, tm_sec= 24, tm_wday= 3, tm_yday= 125, tm_isdst= 0)

time.gmtime([secs])

和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。

       
      
      
      
1
2
       
      
      
      
>>>time.gmtime()
time.struct_time(tm_year= 2011, tm_mon= 5, tm_mday= 5, tm_hour= 6, tm_min= 19, tm_sec= 48, tm_wday= 3, tm_yday= 125, tm_isdst= 0)

time.sleep(secs)

休眠(不做任何事情,推迟)secs秒

time.time()

返回当前时间的时间戳。

       
      
      
      
1
2
       
      
      
      
>>> time.time()
1304575584.1361799

time.mktime(t)

将一个struct_time转化为时间戳。

       
      
      
      
1
2
       
      
      
      
>>> time.mktime(time.localtime())
1304576839.0

time.sleep(secs)

线程推迟指定的时间运行。单位为秒。

time.clock()

这个需要注意,在不同的系统上含义不同。在UNIX系统上,它返回的是“进程时间”,它是用秒表示的浮点数(时间戳)。而在WINDOWS中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行时间。(实际上是以WIN32上QueryPerformanceCounter()为基础,它比毫秒表示更为精确)

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
       
      
      
      
import time
if __name__ == '__main__':
time.sleep( 1)
print "clock1:%s" % time.clock()
time.sleep( 1)
print "clock2:%s" % time.clock()
time.sleep( 1)
print "clock3:%s" % time.clock()
#运行结果
clock1: 3.35238137808e-006
clock2: 1.00004944763
clock3: 2.00012040636
#其中第一个clock()输出的是程序运行时间
#第二、三个clock()输出的都是与第一个clock的时间间隔

time.asctime([t])

把一个表示时间的元组或者struct_time表示为这种形式:’Sun Jun 20 23:21:05 1993’。如果没有参数,将会将time.localtime()作为参数传入。

       
      
      
      
1
2
       
      
      
      
>>> time.asctime()
'Thu May 5 14:55:43 2011'

time.ctime([secs])

把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为None的时候,将会默认time.time()为参数。它的作用相当于time.asctime(time.localtime(secs))。

       
      
      
      
1
2
3
4
5
6
       
      
      
      
>>> time.ctime()
'Thu May 5 14:58:09 2011'
>>> time.ctime(time.time())
'Thu May 5 14:58:39 2011'
>>> time.ctime( 1304579615)
'Thu May 5 15:13:35 2011'

time.strftime(format[, t])

把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。如果元组中任何一个元素越界,ValueError的错误将会被抛出。

日期格式化对照表如下:
|格式 |含义|
|-|-|
|%a |本地(locale)简化星期名称|
|%A |本地完整星期名称|
|%b |本地简化月份名称|
|%B |本地完整月份名称|
|%c |本地相应的日期和时间表示|
|%d |一个月中的第几天(01 - 31)|
|%H |一天中的第几个小时(24小时制,00 - 23)|
|%I |第几个小时(12小时制,01 - 12)|
|%j |一年中的第几天(001 - 366)|
|%m |月份(01 - 12)|
|%M |分钟数(00 - 59)|
|%p |本地am或者pm的相应符|
|%S |秒(01 - 61)|
|%U |一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周|
|%w |一个星期中的第几天(0 - 6,0是星期天)|
|%W |和%U基本相同,不同的是%W以星期一为一个星期的开始|
|%x |本地相应日期|
|%X |本地相应时间|
|%y |去掉世纪的年份(00 - 99)|
|%Y |完整的年份|
|%Z |时区的名字(如果不存在为空字符)|
|%% |‘%’字符|

按常用习惯排列如下:
|格式 |含义|
|-|-|
|%Y |完整的年份 例:2017|
|%m |月份(01 - 12)例:09|
|%d |一个月中的第几天(01 - 31) 例:21|
|%H |一天中的第几个小时(24小时制,00 - 23)|
|%M |分钟数(00 - 59)|
|%S |秒(01 - 61)|
|%B |本地完整月份名称 例:September|
|%A |本地完整星期名称 例:Monday|
|%y |去掉世纪的年份(00 - 99) 即短日期表示 例:17(年)|
|%b |本地简化月份名称 例:Sep|
|%a |本地(locale)简化星期名称 例:Mon|
|%c |本地相应的日期和时间表示 例:09/21/17 17:59:07|
|%x |本地相应日期 例:09/21/17|
|%X |本地相应时间 例:17:59:07|
|%I |第几个小时(12小时制,01 - 12)|
|%p |本地am或者pm的相应符|
|%j |一年中的第几天(001 - 366)|
|%U |一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周|
|%W |和%U基本相同,不同的是%W以星期一为一个星期的开始|
|%w |一个星期中的第几天(0 - 6,0是星期天)|
|%Z |时区的名字(如果不存在为空字符)|
|%% |‘%’字符|

备注:

  1. “%p”只有与“%I”配合使用才有效果。
  2. 文档中强调确实是0 - 61,而不是59,闰年秒占两秒(汗一个)。
  3. 当使用strptime()函数时,只有当在这年中的周数和天数被确定的时候%U和%W才会被计算。

举个例子:

       
      
      
      
1
2
       
      
      
      
>>> time.strftime( "%Y-%m-%d %X", time.localtime())
'2011-05-05 16:37:06'

time.strptime(string[, format])

把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。

       
      
      
      
1
2
       
      
      
      
>>> time.strptime( '2011-05-05 16:37:06', '%Y-%m-%d %X')
time.struct_time(tm_year= 2011, tm_mon= 5, tm_mday= 5, tm_hour= 16, tm_min= 37, tm_sec= 6, tm_wday= 3, tm_yday= 125, tm_isdst= -1)

在这个函数中,format默认为:”%a %b %d %H:%M:%S %Y”。

最后,我们来对time模块进行一个总结。根据之前描述,在Python中共有三种表达方式:1)timestamp 2)tuple或者struct_time 3)格式化字符串。

它们之间的转化如图所示:
Python学习笔记3:Python常见模块的用法_第1张图片

Calendar

此模块的函数都是日历相关的,例如打印某月的字符月历。
星期一是默认的每周第一天,星期天是默认的最后一天。更改设置需调用calendar.setfirstweekday()函数。

常用函数

序号 函数及描述
1 calendar.calendar(year,w=2,l=1,c=6)
返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c。 每日宽度间隔为w字符。每行长度为21 W+18+2 C。l是每星期行数。参数可省略
2 calendar.firstweekday()
返回当前每周起始日期的设置。默认情况下,首次载入caendar模块时返回0,即星期一。
3 calendar.isleap(year)
是闰年返回True,否则为false。
4 calendar.leapdays(y1,y2)
返回在Y1,Y2两年之间的闰年总数。
5 calendar.month(year,month,w=2,l=1)
返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数。参数可省略
6 calendar.monthcalendar(year,month)
返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。Year年month月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始。list形式
7 calendar.monthrange(year,month)
返回两个整数。第一个是该月的星期几的日期码,第二个是该月的日期码。例:(2017, 10) -> (6, 31),第二个参数为当月日期数,第一个参数待深究
8 calendar.prcal(year,w=2,l=1,c=6)
直接打印出整理好的年历。相当于 print calendar.calendar(year,w,l,c).
9 calendar.prmonth(year,month,w=2,l=1)
直接打印出月日历。相当于 print calendar.month(year,w,l,c)。
10 calendar.setfirstweekday(weekday)
设置每周的起始日期码。0(星期一)到6(星期日)。
11 calendar.timegm(tupletime)
和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间辍(1970纪元后经过的浮点秒数)。
12 calendar.weekday(year,month,day)
返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。

建议实际使用 a=calendar.function(), print a方式输出

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
       
      
      
      
# -*- coding: UTF-8 -*-
import calendar
cal = calendar.month( 2016, 1)
print "以下输出2016年1月份的日历:"
print cal
#输出2016年1月份的日历:
January 2016
Mo Tu We Th Fr Sa Su
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

datetime

datatime模块重新封装了time模块,提供更多接口,提供的类有:date,time,datetime,timedelta,tzinfo。

date类

date 类表示一个日期(由年、月、日组成),其原型如下:

class datetime.date(year, month, day)

参数说明:

  1. year 的范围是 [MINYEAR, MAXYEAR],即 [1, 9999];
  2. month 的范围是[1, 12]。(月份是从1开始的,不是从0开始);
  3. day 的最大值根据给定的year, month参数来决定。例如闰年2月份有29天;

date 类定义了一些常用的类方法与类属性:

  1. date.max、date.min:date对象所能表示的最大、最小日期;
  2. date.resolution:date对象表示日期的最小单位。这里是天。
  3. date.today():返回一个表示当前本地日期的 date 对象;
  4. date.fromtimestamp(timestamp):根据给定的时间戮,返回一个 date 对象;
  5. datetime.fromordinal(ordinal):将Gregorian日历时间转换为date对象;(Gregorian Calendar:一种日历表示方法,类似于我国的农历,西方国家使用比较多)

使用示例:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
       
      
      
      
>>> datetime.date.max
datetime.date( 9999, 12, 31)
>>> datetime.date.min
datetime.date( 1, 1, 1)
>>> datetime.date.resolution
datetime.timedelta( 1)
>>> datetime.date.today()
datetime.date( 2016, 5, 12)
>>> datetime.date.fromtimestamp(time.time())
datetime.date( 2016, 5, 12)

date提供的实例方法和属性:

  1. date.year、date.month、date.day:年、月、日;
  2. date.replace(year, month, day):生成一个新的日期对象,用参数指定的年,月,日代替原有对象中的属性。(原有对象仍保持不变)
  3. date.timetuple():返回日期对应的time.struct_time对象;
  4. date.toordinal():返回日期对应的Gregorian Calendar日期; 大专栏  Python学习笔记3:Python常见模块的用法
  5. date.weekday():返回weekday,如果是星期一,返回0;如果是星期2,返回1,以此类推;
  6. data.isoweekday():返回weekday,如果是星期一,返回1;如果是星期2,返回2,以此类推;
  7. date.isocalendar():返回格式如(year,month,day)的元组;
  8. date.isoformat():返回格式如’YYYY-MM-DD’的字符串;
  9. date.strftime(fmt):自定义格式化字符串。

使用示例:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
       
      
      
      
>>> today = datetime.date.today()
>>> today.year
2016
>>> today.month
5
>>> today.day
12
>>> tomorrow = today.replace(day= 13)
>>> tomorrow
datetime.date( 2016, 5, 13)
>>> tomorrow.timetuple()
time.struct_time(tm_year= 2016, tm_mon= 5, tm_mday= 13, tm_hour= 0, tm_min= 0, tm_sec= 0, tm_wday= 4, tm_yday= 134, tm_isdst= -1)
>>> tomorrow.toordinal()
736097
>>> tomorrow.weekday()
4
>>> tomorrow.isoweekday()
5
>>> tomorrow.isocalendar()
( 2016, 19, 5)
>>> tomorrow.isoformat()
'2016-05-13'
>>> tomorrow.strftime( "%y-%m-%d")
'16-05-13'

date 重载了简单的运算符

       
      
      
      
1
2
3
4
5
6
7
8
9
       
      
      
      
#date 允许对日期进行加减和比较:
#日期加上一个间隔,返回一个新的日期对象
date2 = date1 + timedelta
#日期隔去间隔,返回一个新的日期对象
date2 = date1 - timedelta
#两个日期相减,返回一个时间间隔对象
timedelta = date1 - date2
#两个日期进行比较
date1 < date2

使用示例:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
       
      
      
      
>>> now = datetime.date.today()
>>> now
datetime.date( 2016, 5, 12)
>>> now += datetime.date.resolution
>>> now
datetime.date( 2016, 5, 13)
>>> now -= datetime.date.resolution
>>> now
datetime.date( 2016, 5, 12)
>>> now < datetime.date.max
True

Time类

time 类表示时间(由时、分、秒以及微秒组成),其原型如下:

class datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)

参数说明:

  1. hour 的范围为[0, 24),
  2. minute 的范围为[0, 60),
  3. second 的范围为[0, 60),
  4. microsecond 的范围为[0, 1000000),
  5. tzinfo 表示时区信息。

time 类定义的类属性:

  1. time.min、time.max:time类所能表示的最小、最大时间。其中,time.min = time(0, 0, 0, 0), time.max = time(23, 59, 59, 999999);
  2. time.resolution:时间的最小单位,这里是1微秒;

使用示例:

       
      
      
      
1
2
3
4
5
6
       
      
      
      
>>> datetime.time.min
datetime.time( 0, 0)
>>> datetime.time.max
datetime.time( 23, 59, 59, 999999)
>>> datetime.time.resolution
datetime.timedelta( 0, 0, 1)

time类提供的实例方法和属性:

  1. time.hour、time.minute、time.second、time.microsecond:时、分、秒、微秒;
  2. time.tzinfo:时区信息;
  3. time.replace([hour[, minute[, second[, microsecond[, tzinfo]]]]]):创建一个新的时间对象,用参数指定的时、分、秒、微秒代替原有对象中的属性(原有对象仍保持不变);
  4. time.isoformat():返回型如”HH:MM:SS”格式的字符串表示;
  5. time.strftime(fmt):返回自定义格式化字符串。

使用示例:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
       
      
      
      
>>> tm = datetime.time( 18, 18, 18)
>>> tm.hour
18
>>> tm.minute
18
>>> tm.second
18
>>> tm.microsecond
0
>>> tm.tzinfo
>>> tm.isoformat()
'18:18:18'
>>> tm.replace(hour= 20)
datetime.time( 20, 18, 18)
>>> tm.strftime( "%I:%M:%S %p")
'06:18:18 PM'

time 类的对象只能进行比较,无法进行加减操作。

datetime 类

datetime 是 date 与 time 的结合体,包括 date 与 time 的所有信息。其原型如下:

class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)

各参数的含义与date、time的构造函数中的一样,要注意参数值的范围。

datetime类定义的类属性与方法:

  1. datetime.min、datetime.max:datetime所能表示的最小值与最大值;
  2. datetime.resolution:datetime最小单位;
  3. datetime.today():返回一个表示当前本地时间的datetime对象;
  4. datetime.now([tz]):返回一个表示当前本地时间的datetime对象,如果提供了参数tz,则获取tz参数所指时区的本地时间;
  5. datetime.utcnow():返回一个当前utc时间的datetime对象;
  6. datetime.fromtimestamp(timestamp[, tz]):根据时间戮创建一个datetime对象,参数tz指定时区信息;
  7. datetime.utcfromtimestamp(timestamp):根据时间戮创建一个datetime对象;
  8. datetime.combine(date, time):根据date和time,创建一个datetime对象;
  9. datetime.strptime(date_string, format):将格式字符串转换为datetime对象,data 与 time 类没有提供该方法。

使用示例:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
       
      
      
      
>>> datetime.datetime.min
datetime.datetime( 1, 1, 1, 0, 0)
>>> datetime.datetime.max
datetime.datetime( 9999, 12, 31, 23, 59, 59, 999999)
>>> datetime.datetime.resolution
datetime.timedelta( 0, 0, 1)
>>> print datetime.datetime.resolution
0: 00: 00.000001
>>> today = datetime.datetime.today()
>>> today
datetime.datetime( 2016, 5, 12, 12, 46, 47, 246240)
>>> datetime.datetime.now()
datetime.datetime( 2016, 5, 12, 12, 47, 9, 850643)
>>> datetime.datetime.utcnow()
datetime.datetime( 2016, 5, 12, 4, 47, 42, 188124)
>>> datetime.datetime.fromtimestamp(time.time())
datetime.datetime( 2016, 5, 12, 12, 48, 40, 459676)
>>> datetime.datetime.combine(datetime.date( 1990, 10, 05), datetime.time( 18, 18, 18))
datetime.datetime( 1990, 10, 5, 18, 18, 18)
>>> datetime.datetime.strptime( "2010-04-07 01:48:16.234000", "%Y-%m-%d %H:%M:%S .%f")
datetime.datetime( 2010, 4, 7, 1, 48, 16, 234000)

datetime 的实例方法与属性

datetime类提供的实例方法与属性大部分功能与 date 和 time 类似,这里仅罗列方法名不再赘述:

  1. datetime.year、month、day、hour、minute、second、microsecond、tzinfo:
  2. datetime.date():获取date对象;
  3. datetime.time():获取time对象;
  4. datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]]):
  5. datetime.timetuple()
  6. datetime.utctimetuple()
  7. datetime.toordinal()
  8. datetime.weekday()
  9. datetime.isocalendar()
  10. datetime.isoformat([sep])
  11. datetime.ctime():返回一个日期时间的C格式字符串,等效于time.ctime(time.mktime(dt.timetuple()));
  12. datetime.strftime(format)

datetime 对象同样可以进行比较,或者相减返回一个时间间隔对象,或者日期时间加上一个间隔返回一个新的日期时间对象。

timedelta 类

datetime.timedelta 对象代表两个时间之间的的时间差,两个 date 或 datetime 对象相减时可以返回一个timedelta 对象。其原型如下:

class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

所有参数可选,且默认都是0,参数的值可以是整数,浮点数,正数或负数。

内部只存储days,seconds,microseconds,其他参数的值会自动按如下规则抓转换:

  1. 1 millisecond(毫秒) 转换成 1000 microseconds(微秒)
  2. 1 minute 转换成 60 seconds
  3. 1 hour 转换成 3600 seconds
  4. 1 week转换成 7 days

b = a + datetime.timedelta(hours=5)
c = a + datetime.timedelta(weeks=1)

三个参数的取值范围分别为:

  1. 0 <= microseconds < 1000000
  2. 0 <= seconds < 3600*24 (the number of seconds in one day)
  3. -999999999 <= days <= 999999999

timedelta 类定义的类属性:

  1. timedelta.min:时间间隔对象的最小值,即 timedelta(-999999999).
  2. timedelta.max:时间间隔对象的最大值,即 timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999).
  3. timedelta.resolution:时间间隔的最小单位,即 timedelta(microseconds=1).

使用示例:

       
      
      
      
1
2
3
4
5
6
7
8
       
      
      
      
>>> datetime.timedelta.min
datetime.timedelta( -999999999)
>>> datetime.timedelta.max
datetime.timedelta( 999999999, 86399, 999999)
>>> datetime.timedelta.resolution
datetime.timedelta( 0, 0, 1)
>>> print datetime.timedelta.resolution
0: 00: 00.000001

timedelta 实例方法

  1. timedelta.total_seconds():计算时间间隔的总秒数

使用示例:

       
      
      
      
1
2
       
      
      
      
>>> datetime.timedelta.resolution.total_seconds()
1e-06

timeit

timeit模块提供了一种简便的方法来为Python中的小块代码进行计时。它有三种使用方式,从命令行调用,从Python交互解释器调用,或者直接在脚本代码中进行调用。基于实际应用出发,本文阐述timeit模块在交互解释器以及脚本中的基础使用方法。

主要方法

timeit模块主要方法有三个,timeit()、Timer()和repeat()用法。

       
      
      
      
1
2
3
4
5
6
       
      
      
      
timeit(stmt= "pass", setup= "pass", timer=default_timer, number=default_number)
= Timer(stmt, setup, timer).timeit(number)
repeat(stmt= "pass", setup= "pass", timer=default_timer, repeat=default_repeat, number=default_number)
= Timer(stmt, setup, timer).repeat(repeat, number)
#repeat() 方法返回以秒记录的每个测试循环的耗时列表。

其中:

  1. stmt是执行语句,setup是导入执行语句环境。repeat 是重复整个测试的次数,number 是每个测试中执行语句的次数。
    2.default_timer 在 win32 下是 time.clock(),在 linux 下是 time.time()
  2. default_repeat = 3,default_number = 1000000

上述用法示例可如下:

       
      
      
      
1
2
3
4
5
6
7
8
       
      
      
      
>>> import timeit
>>> t = timeit.Timer( "soundex.soundex('Pilgrim')", "import soundex")
>>> t.timeit()
8.21683733547
>>> t.repeat( 3, 2000000)
[ 16.48319309109, 16.46128984923, 16.44203948912]
>>> min(t.repeat( 3, 1000000)) #返回测试最小值
8.22203948912

或如下使用:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
       
      
      
      
# -*- coding: utf8 -*-
import random
import timeit
def randDiff( k,n ):
# '产生k个不相等的从1到n的随机数'
p = []
y1 = [random.randrange( 1,n+ 1) for i in range(n)]
y2 = []
y2.extend(y1)
y1.sort()
for j in range(k):
temp1 = y1[j]
temp2 = y2.index(temp1)
p.append(temp2 + 1)
y2[temp2] = -1
return p
def randDif(k,n):
'新函数,生成k个1到n之间不相等的随机数'
if k>n:
return []
a = range( 1,n+ 1)
random.shuffle(a)
return a[:k]
if __name__== '__main__':
print timeit.repeat( "randDiff(3, 10)", "from __main__ import randDiff", timeit.default_timer, 3, 10000)
print timeit.repeat( "randDif(3, 10)", "from __main__ import randDif", timeit.default_timer, 3, 10000)

在Python交互解释器中的使用

timeit函数基本用法

       
      
      
      
1
2
       
      
      
      
import timeit
timeit.timeit(stmt= 'pass', setup= 'pass', timer=, number= 1000000)

使用示例:

       
      
      
      
1
2
3
       
      
      
      
>>> import timeit
>>>timeit.timeit( '"-".join(str(n) for n in range(100))', number= 10000)
0.21051692962646484

repeat函数

repeat函数,指定整个试验的重复次数,返回一个包含了每次试验的执行时间的列表。

       
      
      
      
1
2
       
      
      
      
>>> timeit.repeat( '"-".join(str(n) for n in range(100))',repeat= 3, number= 10000)
[ 0.21938705444335938, 0.21767210960388184, 0.21688294410705566]

在脚本程序中的使用

timeit模块同样可以在脚本中直接使用。使用方法还是调用上述的函数。但是在脚本中时需要为setup传入一条字符串形式的语句,用于构建执行环境。也可参照基本用法处的代码示例。

       
      
      
      
1
2
3
4
5
6
7
8
9
       
      
      
      
import timeit
def test(): # 需要执行的function函数
L = []
for i in range( 100):
L.append(i)
if __name__ == '__main__':
print timeit.timeit( "test()", setup= "from __main__ import test")

random

random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串。

random的用法主要包括random()、uniform()、randrang()、choice()、shuffle()、sample()几种用法。

random.random()

用于生成一个随机浮点数:range[0.0,1.0)

       
      
      
      
1
2
       
      
      
      
import random
random.random() #输出 0.5487876445645461

random.uniform(a,b)

用于生成一个指定范围内的随机浮点数,a,b为上下限,只要a!=b,就会生成介于两者之间的一个浮点数,若a=b,则生成的浮点数就是a

       
      
      
      
1
2
3
4
       
      
      
      
import random
random.uniform( 10, 20) #输出 15.999997038152358
random.uniform( 20, 10) #输出 12.718038067741021
random.uniform( 10, 10) #输出 10.0

random.randint(a,b)

用于生成一个指定范围内的整数,a为下限,b为上限,生成的随机整数a<=n<=b;若a=b,则n=a;若a>b,报错

       
      
      
      
1
2
3
4
       
      
      
      
import random
random.randint( 10, 20) #输出 12
random.randint( 10, 10) #输出 10
random.randint( 20, 10) #Error

random.randrange([start], stop [,step])

从指定范围内,按指定基数递增的集合中获取一个随机数,基数缺省值为1

       
      
      
      
1
2
3
4
       
      
      
      
import random
random.randrange( 10, 100) #输出为10到100间的任意数
random.randrange( 10, 100, 4) #输出为10到100内以4递增的序列[10,14,18,22...]
random.choice(range( 10, 100, 4)) #输出在结果上与上一条等效

random.choice(sequence)

从序列中获取一个随机元素,参数sequence表示一个有序类型,并不是一种特定类型,泛指list,tuple,字符串等

       
      
      
      
1
2
3
4
5
6
7
8
9
       
      
      
      
import random
random.choice(range( 10)) #输出0到10内随机整数
random.choice(range( 10, 100, 2)) #输出随机值[10,12,14,16...]
random.choice( "I love python") #输出随机字符I,o,v,p,y...
random.choice(( "I love python")) #同上
random.choice([ "I love python"]) #输出“I love python”
random.choice( "I", "love", "python") #Error
random.choice(( "I", "love", "python")) #输出随机字符串“I”,“love”,“python”
random.choice([ "I", "love", "python"]) #输出随机字符串“I”,“love”,“python”

random.shuffle(x[,random])

用于将一个列表中的元素打乱

       
      
      
      
1
2
3
4
       
      
      
      
import random
list=[ 'I', 'love', 'python', 'very', 'much']
random.shuffle(list)
print list #输出乱序list

random.sample(sequence,k)

从指定序列中随机获取k个元素作为一个片段返回,sample函数不会修改原有序列

       
      
      
      
1
2
3
4
5
6
7
8
9
10
       
      
      
      
import random
a= '123456789'
b=[ 1, 2, 3, 4, 5, 6, 7, 8, 9]
c=[ 'a', 'b', 'c', 'd', 'e']
random.sample(a, 3)
random.sample(b, 3)
random.sample(c, 3) #随机取三个元素最为一个片段返回[6,4,3]
print a
print b
print c #a,b,c值不变

shelve

Shelve是python中一个用于持久化存储的模块,采用字典的存储形式。Shelve模块的好处是,基本上任何python对象都可以作为存储的键。作为一种简单的数据存储方案,其最有用的函数为open()

open()函数接收的参数就是文件名,然后返回一个shelf对象,可以用它来存储东西,也可以简单地把他当作一个字典。当存储完毕的时候,调用close()函数来关闭 。

需要注意的是,为了正确地使用shelve模块修改存储的对象,必须将临时变量绑定到获得的副本上,并且在修改后重新存储这个副本。或者直接将open()中writeback参数设为True。否则会导致修改后的内容没有存储好,导致数据丢失。

       
      
      
      
1
2
3
4
5
6
       
      
      
      
>>> import shelve
>>> s = shelve.open( 'test.dat')
>>> s[ 'x'] = [ 'a', 'b', 'c']
>>> s[ 'x'].append( 'd')
>>> s[ 'x']
[ 'a', 'b', 'c']

解决办法之一为将临时变量绑定到获得的副本上。

       
      
      
      
1
2
3
4
5
       
      
      
      
>>> temp = s[ 'x']
>>> temp.append( 'd')
>>> s[ 'x'] = temp
>>> s[ 'x']
[ 'a', 'b', 'c', 'd']

一个完整的示例如下:

创建shelf对象,使用函数shelve.open()(使用的是anydbm)来存储数据。使用类或简单的调用。

       
      
      
      
1
2
3
4
5
6
7
       
      
      
      
import shelve
s = shelve.open( 'test_shelf.db') # 创建test_shelf.db文件进行存储
try:
s[ 'key1'] = { 'int': 10, 'float': 9.5, 'string': 'Sample Data'}  # 写入key1,值可以是python支持的对象,看起来和字典的用法一样
finally:
s.close()

注意要使用try...finally...来调用。

访问已存储的数据,打开shelf,可以像字典一样进行使用。

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
       
      
      
      
s = shelve.open( 'test_shelf.db') # 打开已存在的数据文件
try:
existing = s[ 'key1'] # 获取之前存储的key1
finally:
s.close()
print(existing) # 打印s['key1'],会得到刚才存储的数据
#执行结果
>>> python shelve_create.py
>>> python shelve_existing.py
{ 'int': 10, 'float': 9.5, 'string': 'Sample data'}

dbm模块不支持多个应用同时写入同一数据库,如果客户端或程序不会修改shelf,请指定shelve以只读方式打开数据库。

       
      
      
      
1
2
3
4
5
6
7
       
      
      
      
s = shelve.open( 'test_shelf.db', flag= 'r') # 打开时指定flag=‘r',只读模式打开
try:
existing = s[ 'key1']
finally:
s.close()
print existing

当数据库以只读模式打开,但又试图更改数据库时,会引起一个访问出错异常。这一异常类型依赖于在创建数据库时被anydbm选择的数据库模块。

写回示例。默认情况下,Shelves不去追踪可变对象的修改。意思就是,如果你改变了已存储在shelf中的一个项目的内容,就必须重新存储该项目来更新shelf.

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
       
      
      
      
s = shelve.open( 'test_shelf.db')
try:
print s[ 'key1']
s[ 'key'][ 'new_value'] = 'this is not here before'
finally:
s.close()
s = shelve.open( 'test_shelf.db', writeback = True) # 设置写回或同步
try:
print s[ 'key1']
finally:
s.close()

在这个例子中,没有对字典的关键字key1的内容进行存储,虽然打开时设置了writeback,因此重新打开shelf时,key1内容没有改变。

       
      
      
      
1
2
3
4
       
      
      
      
>>> python shelve_create.py
>>> python shelve_withoutwriteback.py
{ 'int': 10, 'float': 9.5, 'string': 'Sample data'}
{ 'int': 10, 'float': 9.5, 'string': 'Sample data'}

为了自动捕捉存储在shelf中的可变对象所发生的改变,需改变前设置writeback可用.writeback标志导致shelf使用一缓存来记住从数据库中调出的所有对象。当shelf关闭的时候,每一个缓存中的对象也重新写回数据库。

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
       
      
      
      
s = shelve.open( 'test_shelf.db', writeback= True)
try:
print(s[ 'key1'])
s[ 'key1'][ 'new_value'] = 'this was not here before'
print(s[ 'key1'])
finally;
s.close()
s = shelve.open( 'test_shelf.db', writeback= True)
try:
print(s[ 'key1'])
finally:
s.close()
#执行结果
>>> python shelve_create.py
>>> python shelve_writeback.py
{ 'int': 10, 'float': 9.5, 'string': 'Sample data'}
{ 'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}
{ 'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}

虽然使用writeback模式可用减少出错几率,也能更加透明化对象的持久性。但是,不是每种情况都要使用writeback模式。原因看到前面的示例,应该能猜到。当shelf打开时,缓存就要占用额外的内存。 并且,当shelf关闭时,同样会对缓存中的对象再次写回数据库,增加了开销。即使没有进行改变,仍然会进行数据写回。比较好的方式是,确认需要写入数据时,再设置writeback,读数据时设置只读或默认即可。

csv

csv库可识别Microsoft Excel所使用的CSV编码规则。csv库还包含修改分隔字符等,出于实际csv文件应用考虑,这里不阐述,如有需要可之后自行查阅。

CSV格式简介

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。

CSV文件注意点

如果你正在读取CSV数据并将它们转换为命名元组,需要注意对列名进行合法性认证。一个CSV格式文件有一个包含非法标识符的列头行,这样最终会导致在创建一个命名元组时产生一个ValueError异常而失败。为了解决这问题,你可能不得不先去修正列标题。

       
      
      
      
1
2
3
4
5
6
7
8
9
       
      
      
      
import re
with open( 'stock.csv') as f:
f_csv = csv.reader(f)
headers = [ re.sub( '[^a-zA-Z_]', '_', h) for h in next(f_csv) ]
Row = namedtuple( 'Row', headers)
for r in f_csv:
row = Row(*r)
# Process row
...

还有重要的一点需要强调的是,CSV产生的数据都是字符串类型的,它不会做任何其他类型的转换。如果你需要做这样的类型转换,你必须自己手动去实现。

简单使用

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
       
      
      
      
# 读取csv文件
import csv
with open( 'some.csv', 'rb') as f: # 采用b的方式处理可以省去很多问题
reader = csv.reader(f)
for row in reader:
# do something with row, such as row[0],row[1]
import csv
with open( 'some.csv', 'wb') as f: # 采用b的方式处理可以省去很多问题
writer = csv.writer(f)
writer.writerows(someiterable)

字典方式读写

csv还提供了一种类似于字典方式的读写,方式如下:

       
      
      
      
1
2
3
       
      
      
      
class csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)
class csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)

其中fieldnames指定字典的key值,如果reader里没有指定那么默认第一行的元素(header),在writer里一定要指定这个。

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
       
      
      
      
# 读
>>> import csv
>>> with open( 'names.csv') as csvfile:
... reader = csv.DictReader(csvfile)
... for row in reader:
... print(row[ 'first_name'], row[ 'last_name'])
...
Baked Beans
Lovely Spam
Wonderful Spam
# 写
import csv
with open( 'names.csv', 'w') as csvfile:
fieldnames = [ 'first_name', 'last_name']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({ 'first_name': 'Baked', 'last_name': 'Beans'})
writer.writerow({ 'first_name': 'Lovely', 'last_name': 'Spam'})
writer.writerow({ 'first_name': 'Wonderful', 'last_name': 'Spam'})

有关csv库的一些操作可以参考读写CSV数据一文。

CSV模块操作示例

输入文件:stocks.csv

       
      
      
      
1
2
3
4
5
6
7
       
      
      
      
Symbol,Price,Date,Time,Change,Volume
"AA", 39.48, "6/11/2007", "9:36am", -0.18, 181800
"AIG", 71.38, "6/11/2007", "9:36am", -0.15, 195500
"AXP", 62.58, "6/11/2007", "9:36am", -0.46, 935000
"BA", 98.31, "6/11/2007", "9:36am",+ 0.12, 104800
"C", 53.08, "6/11/2007", "9:36am", -0.25, 360900
"CAT", 78.29, "6/11/2007", "9:36am", -0.23, 225400

输出文件:dest.csv

       
      
      
      
1
2
3
4
       
      
      
      
Symbol,Price,Date,Time,Change,Volume
AA, 39.48, 6/ 11/ 2007, 9: 36am, -0.18, 181800
AIG, 71.38, 6/ 11/ 2007, 9: 36am, -0.15, 195500
AXP, 62.58, 6/ 11/ 2007, 9: 36am, -0.46, 935000

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
       
      
      
      
# coding: UTF-8
"""
Created on 2015/9/30 14:55
@author: 'WX'
"""
from collections import namedtuple
import csv
if __name__ == "__main__":
fileName = 'stocks.csv'
writeFileName = 'dest.csv'
with open(fileName) as f:
reader = csv.reader(f)
headers = next(reader)
print( "使用下标进行访问")
for row in reader:
# 可以使用下标进行访问,row是一个元组
length = len(row)
for i in range(length):
print(row[i], end= 't')
print()
print( '------------------------------------------------')
with open(fileName) as f:
# 使用命名元组访问
reader = csv.reader(f)
headers = next(reader)
Row = namedtuple( 'Row', headers)
print( "使用命名元组进行访问")
for r in reader:
row = Row(*r)
# 这时候就可以使用首行的列名来进行访问了
line = '%st%st%st%st%st%s' % (row.Symbol, row.Price, row.Date, row.Time, row.Change, row.Volume)
print(line)
print( '------------------------------------------------')
with open(fileName) as f:
# 将内容读取到字典序列中,然后用key去读取
dict_reader = csv.DictReader(f)
print( "使用字典序列进行访问")
for row in dict_reader:
line = '%st%st%st%st%st%s' % (
row[ 'Symbol'], row[ 'Price'], row[ 'Date'], row[ 'Time'], row[ 'Change'], row[ 'Volume'])
print(line)
print( '------------------------------------------------')
print( "使用元组方式写入,SUCCESS!")
with open(writeFileName, mode= 'w', newline= '') as wf:
headers = [ 'Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']
rows = [( 'AA', 39.48, '6/11/2007', '9:36am', -0.18, 181800),
( 'AIG', 71.38, '6/11/2007', '9:36am', -0.15, 195500),
( 'AXP', 62.58, '6/11/2007', '9:36am', -0.46, 935000),
]
writer = csv.writer(wf)
writer.writerow(headers)
writer.writerows(rows)
print( "使用字典方式写入,SUCCESS!")
# 在Windows平台需要指定newline='',否则在两行内容之间会多出一行空行
with open(writeFileName, mode= 'w', newline= '') as wf:
headers = [ 'Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']
rows = [{ 'Symbol': 'AA', 'Price': 39.48, 'Date': '6/11/2007',
'Time': '9:36am', 'Change': -0.18, 'Volume': 181800},
{ 'Symbol': 'AIG', 'Price': 71.38, 'Date': '6/11/2007',
'Time': '9:36am', 'Change': -0.15, 'Volume': 195500},
{ 'Symbol': 'AXP', 'Price': 62.58, 'Date': '6/11/2007',
'Time': '9:36am', 'Change': -0.46, 'Volume': 935000}, ]
writer = csv.DictWriter(wf, headers)
writer.writeheader()
writer.writerows(rows)
# 更换一种分隔符写入文件
with open(writeFileName, mode= 'w', newline= '') as wf:
headers = [ 'Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']
rows = [( 'AA', 39.48, '6/11/2007', '9:36am', -0.18, 181800),
( 'AIG', 71.38, '6/11/2007', '9:36am', -0.15, 195500),
( 'AXP', 62.58, '6/11/2007', '9:36am', -0.46, 935000),
]
writer = csv.writer(wf, delimiter= ';')
writer.writerow(headers)
writer.writerows(rows)
print( "使用分好作为分隔符写入,SUCCESS!")

控制台输出

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
       
      
      
      
C:Python34python.exe E:/workspaces/Python3/edu/shu/python/shumo/CsvUtil.py
使用下标进行访问
AA 39.48 6/ 11/ 2007 9: 36am -0.18 181800
AIG 71.38 6/ 11/ 2007 9: 36am -0.15 195500
AXP 62.58 6/ 11/ 2007 9: 36am -0.46 935000
BA 98.31 6/ 11/ 2007 9: 36am + 0.12 104800
C 53.08 6/ 11/ 2007 9: 36am -0.25 360900
CAT 78.29 6/ 11/ 2007 9: 36am -0.23 225400
------------------------------------------------
使用命名元组进行访问
AA 39.48 6/ 11/ 2007 9: 36am -0.18 181800
AIG 71.38 6/ 11/ 2007 9: 36am -0.15 195500
AXP 62.58 6/ 11/ 2007 9: 36am -0.46 935000
BA 98.31 6/ 11/ 2007 9: 36am + 0.12 104800
C 53.08 6/ 11/ 2007 9: 36am -0.25 360900
CAT 78.29 6/ 11/ 2007 9: 36am -0.23 225400
------------------------------------------------
使用字典序列进行访问
AA 39.48 6/ 11/ 2007 9: 36am -0.18 181800
AIG 71.38 6/ 11/ 2007 9: 36am -0.15 195500
AXP 62.58 6/ 11/ 2007 9: 36am -0.46 935000
BA 98.31 6/ 11/ 2007 9: 36am + 0.12 104800
C 53.08 6/ 11/ 2007 9: 36am -0.25 360900
CAT 78.29 6/ 11/ 2007 9: 36am -0.23 225400
------------------------------------------------
使用元组方式写入,SUCCESS!
使用字典方式写入,SUCCESS!
Process finished with exit code 0

最后,如果你读取CSV数据的目的是做数据分析和统计的话,你可能需要看一看Pandas包。Pandas包含了一个非常方便的函数叫pandas.read_csv(),它可以加载CSV数据到一个DataFrame对象中去。然后利用这个对象你就可以生成各种形式的统计、过滤数据以及执行其他高级操作了。

matplotlib

matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地进行制图。而且也可以方便地将它作为绘图控件,嵌入GUI应用程序中。

matplotlib的pyplot子库提供了和matlab类似的绘图API,方便用户快速绘制2D图表。

一个matplotlib绘图的示例如下:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
       
      
      
      
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace( 0, 10, 1000)
y = np.sin(x)
z = np.cos(x** 2)
plt.figure(figsize=( 8, 4))
plt.plot(x,y,label= "$sin(x)$",color= "red",linewidth= 2)
plt.plot(x,z, "b--",label= "$cos(x^2)$")
plt.xlabel( "Time(s)")
plt.ylabel( "Volt")
plt.title( "PyPlot First Example")
plt.ylim( -1.2, 1.2)
plt.legend()
plt.show()

从上面,我们能看到matplotlib绘图模块的几个重要部分,分别是plt.figureplt.plotplt.xlabelplt.ylabelplt.titleplt.xlimplt.ylimplt.legndplt.show等。此外还包括plt.savefigplt.axes

figure

figure函数的作用是创建一个绘图对象,并且使它成为当前的绘图对象,也可以不创建绘图对象直接调用接下来的plot函数直接绘图,matplotlib会为我们自动创建一个绘图对象。如果需要同时绘制多幅图表的话,可以是给figure传递一个整数参数指定图标的序号,如果所指定序号的绘图对象已经存在的话,将不创建新的对象,而只是让它成为当前绘图对象。

figure(figsize=(8,6), dpi=80),这句的功能是“创建一个 8 6 点(point)的图,并设置分辨率为 80”。通过figsize参数可以指定绘图对象的宽度和高度,单位为英寸;dpi参数指定绘图对象的分辨率,即每英寸多少个像素,默认值为80。因此本例中所创建的图表窗口的宽度为880 = 640像素,高度则为6*80=480像素。

除了设置图片像素和分辨率之外,还可以设置保存图片的像素和分辨率,通过savefig函数实现,这点会在之后阐述。

plot

plot函数是直接的绘图部分,plt.plot后参数包括以下内容:

  • x y函数/取值,如果为数组则需要转为向量形式,允许 x1,y1,x2,y2在同一张图中绘制多个图像(也可调用两次plot函数)
  • 格式化参数,其包括了color/style等样式,指定线条的颜色样式等。采用格式化参数可快速指定线条样式。具体样式会在下面阐述
  • linewidth,指定曲线的宽度
  • label值:指所绘制曲线的对应名称,此部分在plt.legend中显示。字符串前后添加”$”符号,会显示为其latex格式的数学公式

格式化参数部分,包括颜色、线条标记、线条属性三部分。参数分别为colormarkerlinestyle,也可单独设置各参数。

线条颜色

标记 描述
b 蓝色
g 绿色
r 红色
c 青色
m 洋红色
y 黄色
k 黑色
w 白色

以上是常用颜色,当需要使用其他颜色时,也可以使用HTML十六进制字符串 color=’#eeefff’来调用颜色

线条属性

标记 描述
- 实线
破折线
-. 点划线
: 虚线
. 点标记
, 像素标记

线条标记

标记 描述
o 圆圈
v 倒三角
^ 正三角
< 左转90度的三角形
> 右转90度的三角形
1 禾苗形状1
2 禾苗形状2
3 禾苗形状3
4 禾苗形状4
s 正方形
p 五边形
* *标记
h 六边形1
H 六边形2
+ +标记
x x标记
D 菱形
d 小菱形
竖线
_ 水平线

需要注意的是,当有线条标记这个属性时,即使添加了线条属性这部分,也只会在对应的函数值处展示线条标记,连续的线条样式跟随线条属性而不跟随线条标记。

基本配置

采用matplotlib绘图时,有一些基本配置信息。

  • plt.xlabel:x轴坐标
  • plt.ylabel:y轴坐标
  • plt.title:图表名称
  • plt.xlim:x轴范围
  • plt.ylim:y轴范围
  • plt.legend:显示图例

图例legend的用法为legend(loc='upper left')。除了图例之外,还可以直接将曲线代表的函数绘制在曲线旁边,所用的函数为text函数。用法为text(1, 7.5, r'$10^x$', fontsize=16),即text(x_zuobiao, y_zuobiao, biaodashi, fontsize)。当然还有annotate用法,此处不展开描述。

其中,x/y周坐标范围也可用plt.axis([-0.1, 4.5, -0.1, 4.5])形式来表示。

以上绘制图表完毕后,可采用ply.show()来显示图表。同时也可以采用savefig("test.png",dpi=72)来保存图表,可设置保存的图表像素大小。

除了上述之外,还包括一些细节设置方面,如x/y轴的刻度间距等。

刻度间距可通过下述来设置:

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
       
      
      
      
# 设置横轴的上下限
xlim( -4.0, 4.0)
# 设置横轴记号,[-4,4],共9个刻度线
xticks(np.linspace( -4, 4, 9,endpoint= True))
# 设置纵轴的上下限
ylim( -1.0, 1.0)
# 设置纵轴记号,[-1,1],共5个刻度线
yticks(np.linspace( -1, 1, 5,endpoint= True))
# 还可以有另一种表示方式
# 即指定各自的刻度值
xticks( [-np.pi, -np.pi/ 2, 0, np.pi/ 2, np.pi])
yticks([ -1, 0, + 1])
# 将上述表示为π形式的坐标值
xticks([-np.pi, -np.pi/ 2, 0, np.pi/ 2, np.pi],
[ r'$-pi$', r'$-pi/2$', r'$0$', r'$+pi/2$', r'$+pi$'])
yticks([ -1, 0, + 1],
[ r'$-1$', r'$0$', r'$+1$'])

子图 subplot

当涉及到绘出多个图像时,除了采用多次plot将图像绘在同一张表中,还可以采用子图形式。利用subplot分配图表位置(依次排序)和采用的图表,进行绘图。subplot(221),表示分成2行2列,当前采用的是第一个图表。当各参数都小于10时,可简写为221形式,超过时需要表示为(2,2,1)形式。

对于多子图的绘图,每个子图绘制完毕之后再绘制下一个子图。即:

       
      
      
      
1
2
3
4
5
       
      
      
      
plt.subplot( 211)
plt.plot(x,y)
plt.subplot( 212)
plt.plot(x,y)

显示中文

matplotlib的缺省配置文件中所使用的字体无法正确显示中文。为了让图表能正确显示中文,可以有几种解决方案。

  • 在程序中直接指定字体
  • 在程序开头修改配置字典rcParams
  • 修改配置文件

下面是通过修改字体实现的一种方法

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
       
      
      
      
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
import numpy as np
font = FontProperties(fname= r"c:windowsfontssimsun.ttc", size= 14)
t = np.linspace( 0, 10, 1000)
y = np.sin(t)
plt.plot(t, y)
plt.xlabel( u"时间", fontproperties=font)
plt.ylabel( u"振幅", fontproperties=font)
plt.title( u"正弦波", fontproperties=font)
plt.show()

绘图示例

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
       
      
      
      
#图例显示
from matplotlib.matlab import *
def f(x, c):
m1 = sin( 2*pi*x)
m2 = exp(-c*x)
return multiply(m1, m2)
x = linspace( 0, 4, 100)
sigma = 0.5
plot(x, f(x, sigma), 'r', linewidth= 2)
xlabel( r'$rm{time} t$', fontsize= 16)
ylabel( r'$rm{Amplitude} f(x)$', fontsize= 16)
title( r'$f(x) rm{is damping with} x$', fontsize= 16)
text( 2.0, 0.5, r'$f(x) = rm{sin}(2 pi x^2) e^{sigma x}$', fontsize= 20)
savefig( 'latex.png', dpi= 75)
show()

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
       
      
      
      
# plt.figure()实现
import matplotlib.pyplot as plt
plt.figure( 1) # 第一张图
plt.subplot( 211) # 第一张图中的第一张子图
plt.plot([ 1, 2, 3])
plt.subplot( 212) # 第一张图中的第二张子图
plt.plot([ 4, 5, 6])
plt.figure( 2) # 第二张图
plt.plot([ 4, 5, 6]) # 默认创建子图subplot(111)
plt.figure( 1) # 切换到figure 1 ; 子图subplot(212)仍旧是当前图
plt.subplot( 211) # 令子图subplot(211)成为figure1的当前图
plt.title( 'Easy as 1,2,3') # 添加subplot 211 的标题

Python学习笔记3:Python常见模块的用法_第2张图片

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
       
      
      
      
# 箱型图
from matplotlib.matlab import *
filename = "d:\wei\exp\current.dat"
X = load(filename)
dp = X[:, 0]
i_mea = X[:, 1]
i_mea_err = X[:, 2]
i_cal = X[:, 3]
i_cal_err = X[:, 4]
width = 3
h1 = bar(dp, i_mea, width, color= 'r', yerr=i_mea_err)
h2 = bar(dp+width, i_cal, width, color= 'b', yerr=i_cal_err)
xlabel( 'Particle diameter (nm)', fontsize= 16)
xticks(dp+width, dp)
ylabel( 'Signal current (nA)', fontsize= 16)
title( 'Measured current vs. calculated current')
legend((h1[ 0], h2[ 0]), ( 'measured current', 'calculated current'), loc= 2)
savefig( 'current.png', dpi= 75)
show()

Python学习笔记3:Python常见模块的用法_第3张图片

       
      
      
      
1
2
3
4
5
6
7
8
       
      
      
      
# 直方图
import numpy as np
import matplot.pyplot as plt
x = np.random.randn( 1000)
plt.hist(x, 50)
plt.show()

Python学习笔记3:Python常见模块的用法_第4张图片

直方图是 Matplotlib 中最简单的图形之一。你只需要给 hist() 函数传入一个包含数据的数组。第二个参数代表数据容器的个数。数据容器代表不同的值的间隔,并用来包含我们的数据。数据容器越多,图形上的数据条就越多。

       
      
      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
       
      
      
      
#标注示例
import numpy as np
import matplotlib.pyplot as plt
ax = plt.subplot( 111)
t = np.arange( 0.0, 5.0, 0.01)
s = np.cos( 2*np.pi*t)
line = plt.plot(t, s, lw= 2)
plt.annotate( 'local max', xy=( 2, 1), xytext=( 3, 1.5),
arrowprops=dict(facecolor= 'black', shrink= 0.05))
plt.ylim( -2, 2)
plt.show()

参见Matplotlib 教程

你可能感兴趣的:(Python学习笔记3:Python常见模块的用法)