知识点
文件操作
<1>打开文件
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件
示例如下:
open(文件名,访问模式)
f = open('test.txt','w')
说明:
访问模式 | 说明 |
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
w | 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
w+ | 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
<2>关闭文件
close()
示例如下:
# 新建一个文件,文件名为:test.txt f = open('test.txt', 'w') # 关闭这个文件 f.close(
文件的读写
<1>写数据(write)
使用write()可以完成向文件写入数据
demo:
f = open('test.txt', 'w') f.write('hello world, i am here!') f.close()
<2>读数据(read)
使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据
demo:
f = open('test.txt', 'r') content = f.read(5) print(content) print("-"*30) content = f.read() print(content) f.close()
<3>读数据(readlines)
就像read没有参数时一样,readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
#coding=utf-8 f = open('test.txt', 'r') content = f.readlines() print(type(content)) i=1 for temp in content: print("%d:%s"%(i, temp)) i+=1 f.close()
运行现象:
<4>读数据(readline)
#coding=utf-8 f = open('test.txt', 'r') content = f.readline() print("1:%s"%content) content = f.readline() print("2:%s"%content) f.close()
应用1:制作文件的备份
任务描述
输入文件的名字,然后程序自动完成对文件进行备份
#coding=utf-8 oldFileName = raw_input("请输入要拷贝的文件名字:") oldFile = open(oldFileName,'rb') # 如果打开文件 if oldFile: # 提取文件的后缀 fileFlagNum = oldFileName.rfind('.') if fileFlagNum > 0: fileFlag = oldFileName[fileFlagNum:] # 组织新的文件名字 newFileName = oldFileName[:fileFlagNum] + '[复件]' + fileFlag # 创建新文件 newFile = open(newFileName, 'wb') # 把旧文件中的数据,一行一行的进行复制到新文件中 for lineContent in oldFile.readlines(): newFile.write(lineContent) # 关闭文件 oldFile.close() newFile.close()
文件的定位读写
<1>获取当前读写的位置
在读写文件的过程中,如果想知道当前的位置,可以使用tell()来获取
# 打开一个已经存在的文件 f = open("test.txt", "r") str = f.read(3) print "读取的数据是 : ", str # 查找当前位置 position = f.tell() print "当前文件位置 : ", position str = f.read(3) print "读取的数据是 : ", str # 查找当前位置 position = f.tell() print "当前文件位置 : ", position f.close()
<2>定位到某个位置
如果在读写文件的过程中,需要从另外一个位置进行操作的话,可以使用seek()
seek(offset, from)有2个参数
offset:偏移量
from:方向
0:表示文件开头
1:表示当前位置
2:表示文件末尾
demo:把位置设置为:从文件开头,偏移5个字节
# 打开一个已经存在的文件 f = open("test.txt", "r") str = f.read(30) print "读取的数据是 : ", str # 查找当前位置 position = f.tell() print "当前文件位置 : ", position # 重新设置位置 f.seek(5,0) # 查找当前位置 position = f.tell() print "当前文件位置 : ", position f.close()
demo:把位置设置为:离文件末尾,3字节处
# 打开一个已经存在的文件 f = open("test.txt", "r") # 查找当前位置 position = f.tell() print "当前文件位置 : ", position # 重新设置位置 f.seek(-3,2) # 读取到的数据为:文件最后3个字节数据 str = f.read() print "读取的数据是 : ", str f.close()
文件重命名、删除
有些时候,需要对文件进行重命名、删除等一些操作,python的os模块中都有这么功能
<1>文件重命名
<1>文件重命名
os模块中的rename()可以完成对文件的重命名操作
rename(需要修改的文件名, 新的文件名)
import os os.rename("毕业论文.txt", "毕业论文-最终版.txt")
<2>删除文件
<2>删除文件
os模块中的remove()可以完成对文件的删除操作
remove(待删除的文件名)
import os os.remove("毕业论文.txt")
文件夹的相关操作
实际开发中,有时需要用程序的方式对文件夹进行一定的操作,比如创建、删除等
就像对文件操作需要os模块一样,如果要操作文件夹,同样需要os模块
<1>创建文件夹
import os os.mkdir("张三")
<2>获取当前目录
import os os.getcwd()
<3>改变默认目录
import os os.chdir("../")
<4>获取目录列表
import os os.listdir("./")
<5>删除文件夹
import os os.rmdir("张三")
应用2:批量修改文件名
#coding=utf-8 # 批量在文件名前加前缀 import os funFlag = 1 # 1表示添加标志 2表示删除标志 folderName = './renameDir/' # 获取指定路径的所有文件名字 dirList = os.listdir(folderName) # 遍历输出所有文件名字 for name in dirList: print name if funFlag == 1: newName = '[东哥出品]-' + name elif funFlag == 2: num = len('[东哥出品]-') newName = name[num:] print newName os.rename(folderName+name, folderName+newName)
异常介绍
示例(打开一个不存在的文件123.txt):
print '-----test--1---' open('123.txt','r') print '-----test--2---'
运行结果:
打开一个不存在的文件123.txt,当找不到123.txt 文件时,就会抛出给我们一个IOError类型的错误,No such file or directory:123.txt (没有123.txt这样的文件或目录)
当Python检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的"异常"
捕获异常
<1>捕获异常 try...except...
try: print '-----test--1---' open('123.txt','r') print '-----test--2---' except IOError: pass
此程序看不到任何错误,因为用except 接收了产生IOError错误,并添加了处理错误的方法
pass 表示实现了相应的实现,但什么也不做;如果把pass改为print语句,那么就会输出其他信息
<2>获取异常的信息描述
try: print num except IOError: print '产生错误了;'
上例程序,已经使用except来捕获异常了,为什么还会看到错误的信息提示?
except捕获的错误类型是IOError,而此时程序产生的异常为 NameError ,所以except没有生效
修改后的代码为:
try: print num except NameError: print '产生错误了;'
<3> except捕获多个异常
#coding=utf-8 try: print '-----test--1---' # 如果123.txt文件不存在,那么会产生 IOError 异常 open('123.txt','r') print '-----test--2---' # 如果num变量没有定义,那么会产生 NameError 异常 print num except (IOError,NameError), errorMsg: #如果想通过一次except捕获到多个异常可以用一个元组的方式 # errorMsg里会保存捕获到的错误信息 print errorMsg
如果想捕获所有的异常,可以省略except后面的变量
但是这种方法不建议大家使用,会隐藏一些开发者没有想到的异常情况
<4> try...finally...
try...finally...语句用来表达这样的情况
不管线捕捉到的是什么错误,无论错误是不是发生,这些代码“必须”运行,比如文件关闭,释放锁,把数据库连接返还给连接池等
import time try: f = file('poem.txt') while True: # our usual file-reading idiom line = f.readline() if len(line) == 0: break time.sleep(2) print line, finally: f.close() print 'Cleaning up...closed the file'
程序读poem.txt文件中每一行数据打印,但是我有意在每打印一行之前用time.sleep方法暂停2秒钟。这样做的原因是让程序运行得慢一些。在程序运行的时候,按Ctrl-c中断/取消程序。
我们可以观察到KeyboardInterrupt异常被触发,程序退出。但是在程序退出之前,finally从句仍然被执行,把文件关闭。
<5> else
咱们应该对
else
并不陌生,在if中,它的作用是当条件不满足时执行的实行;同样在try...except...中也是如果,即如果没有捕获到异常,那么就执行else中的事情
try: num = 100 print num except NameError, errorMsg: print('产生错误了:%s'%errorMsg) else: print('没有捕获到异常,真高兴') finally: print('我一定会执行的哦')
抛出异常
你可以用raise语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是Error或Exception类的子类
下面是一个引发异常的例子:
class ShortInputException(Exception): '''你定义的异常类。''' def __init__(self, length, atleast): Exception.__init__(self) self.length = length self.atleast = atleast try: s = raw_input('请输入 --> ') if len(s) < 3: # raise引发一个你定义的异常 raise ShortInputException(len(s), 3) except EOFError: print '/n你输入了一个结束标记EOF' except ShortInputException, x:#x这个变量被绑定到了错误的实例 print('ShortInputException: 输入的长度是 %d,长度至少应是 %d'% (x.length, x.atleast)) else: print '没有异常发生.'
运行结果如下:
$ python raising.py 请输入 --> 你输入了一个结束标记EOF $ python raising.py 请输入 --> --> ab ShortInputException: 输入的长度是 2, 长度至少应是 3 $ python raising.py 请输入 --> abc 没有异常发生.
模块介绍
<1>Python中的模块
有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句"#include"引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些内置的函数,该怎么处理呢?
在Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块,下面就来了解一下Python中的模块。
说的通俗点:模块就好比是工具包,要想使用这个工具包中的工具(就好比函数),就需要导入这个模块
<2>import
在Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用import math来引入。
import module1,mudule2...
当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。
在调用math模块中的函数时,必须这样引用:
模块名.函数名
有时候我们只需要用到模块中的某个函数,只需要引入该函数即可,此时可以以下方法实现
from 模块名 import 函数名1,函数名2...
不仅可以引入函数,还可以引入一些变量
注意:
通过这种方式引入的时候,调用函数时只能给出函数名,不能给出模块名,但是当两个模块中含有相同名称函数的时候,后面一次引入会覆盖前一次引入。也就是说假如模块A中有函数function(),在模块B中也有函数function(),如果引入A中的function在先、B中的function在后,那么当调用function函数的时候,是去执行模块B中的function函数。
如果想一次性引入math中所有的东西,还可以通过from math import*来实现,但是不建议这么做
<3>from…import
Python的from语句让你从模块中导入一个指定的部分到当前命名空间中。
语法如下:
from modname import name1[, name2[,... nameN]]
例如,要导入模块fib的fibonacci函数,使用如下语句:
from fib import fibonacci
这个声明不会把整个fib模块导入到当前的命名空间中,它只会将fib里的fibonacci单个引入
<4>from … import *
把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:
from modname import *
这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。
<5>定位模块
当你导入一个模块,Python解析器对模块位置的搜索顺序是:
当前目录
如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/
模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
模块制作
<1>定义自己的模块
在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。
比如有这样一个文件test.py,在test.py中定义了函数add
test.py
def add(a,b): return a+b
<2>调用自己定义的模块
那么在其他文件中就可以先import test,然后通过test.add(a,b)来调用了,当然也可以通过from test import add来引入
main.py
import test result = test.add(11,22) print(result)
<3>测试模块
在实际开中,有时一个模块,是一个开发人员进行编写,为了让整个模块中的功能都达到想要的效果,有时编程人员会自行在py文件中添加一些测试信息,例如:
test.py
def add(a,b): return a+b # 用来进行测试 ret = add(12,22) print('int test.py file,,,,12+22=%d'%ret)
如果此时,在其他py文件中引入了此文件的话,想想看,测试的那段代码是否也会执行呢!
main.py
import test result = test.add(11,22) print(result)
运行现象:
至此,可发现test.py中的测试代码,应该是单独执行test.py文件时,才应该执行的,不应该是其他的文件中引用而执行
为了解决这个问题,python在执行一个文件时有个变量__name__
总结:
可以根据__name__变量的结果能够判断出,是直接执行的python脚本还是被引入执行的,
从而能够有选择性的执行测试代码
Python中的包
1.python中的包
包将有联系的模块组织在一起,有效避免模块名称冲突问题,让应用组织结构更加清晰
假定我们的包的例子有如下的目录结构:
Phone/ __init__.py common_util.py Voicedta/ __init__.py Pots.py Isdn.py Fax/ __init__.py G3.py Mobile/ __init__.py Analog.py igital.py Pager/ __init__.py Numeric.py
Phone是最顶层的包,Voicedta等是它的子包。我们可以这样导入子包:
import Phone.Mobile.Analog Phone.Mobile.Analog.dial()
你也可使用from-import实现不同需求的导入
第一种方法是只导入顶层的子包,然后使用属性/点操作符向下引用子包树:
from Phone import Mobile Mobile.Analog.dial('555-1212')
此外,我们可以还引用更多的子包:
from Phone.Mobile import Analog Analog.dial('555-1212')
事实上,你可以一直沿子包的树状结构导入:
from Phone.Mobile.Analog import dial dial('555-1212')
在我们上边的目录结构中,我们可以发现很多的 __init__.py 文件。这些是初始化模块,from-import语句导入子包时需要用到它。如果没有用到,他们可以是空文件。
包同样支持from-import all 语句:
from package.module import*
然而,这样的语句会导入哪些文件取决于操作系统的文件系统。所以我们在__init__.py 中加入 __all__ 变量。该变量包含执行这样的语句时应该导入的模块的名字。它由一个模块名字符串列表组成.。
2. __all__
Python的moudle是很重要的一个概念,moudle里一般都会有一个__init__.py文件。有的__init__.py中是空白,有的却会有__all__参数。
如果其他页面import的时候,如果__init__.py是空白的,可以直接import到moudle的所有函数。而如果__init__.py中定义了__all__,则import的时候只会导入__all__部分定义的内容。
例如,我们可以这样组织一个package:
package1/ __init__.py subPack1/ __init__.py module_11.py module_12.py module_13.py subPack2/ __init__.py module_21.py module_22.py
__init__.py可以为空,只要它存在,就表明此目录应被作为一个package处理。
当然,__init__.py中也可以设置相应的内容
现在我们在module_11.py中定义一个函数:
def funA(): print "funcA in module_11"
在顶层目录(也就是package1所在的目录,当然也参考上面的介绍,将package1放在解释器能够搜索到的地方)运行python:
>>>from package1.subPack1.module_11 import funcA
>>>funcA()
funcA in module_11
这样,我们就按照package的层次关系,正确调用了module_11中的函数。
细心的同学会发现,有时在import语句中会出现通配符*,导入某个module中的所有元素,这是怎么实现的呢?
答案就在__init__.py中。我们在subPack1的__init__.py文件中写
__all__ =['module_13','module_12']
然后进入python
>>>from package1.subPack1 import*
>>>module_11.funcA()
Traceback(most recent call last):
File"", line 1,in
ImportError:No module named module_11
也就是说,以*导入时,package内的module是受__init__.py限制的。
模块发布
1.mymodule目录结构体如下:
. ├── setup.py ├── suba │ ├── aa.py │ ├── bb.py │ └── __init__.py └── subb ├── cc.py ├── dd.py └── __init__.py
2.编写setup.py,py_modules需指明所需包含的py文件
from distutils.core import setup setup(name="xwp", version="1.0", description="xwp's module", author="FLY", py_modules=['suba.aa', 'suba.bb', 'subb.cc', 'subb.dd'])
3.构建模块
python setup.py build
构建后目录结构
. ├── build │ └── lib.linux-i686-2.7 │ ├── suba │ │ ├── aa.py │ │ ├── bb.py │ │ └── __init__.py │ └── subb │ ├── cc.py │ ├── dd.py │ └── __init__.py ├── setup.py ├── suba │ ├── aa.py │ ├── bb.py │ └── __init__.py └── subb ├── cc.py ├── dd.py └── __init__.py
4.生成发布压缩包
python setup.py sdist
打包后,生成最终发布压缩包xwp-1.0.tar.gz , 目录结构
. ├── build │ └── lib.linux-i686-2.7 │ ├── suba │ │ ├── aa.py │ │ ├── bb.py │ │ └── __init__.py │ └── subb │ ├── cc.py │ ├── dd.py │ └── __init__.py ├── dist │ └── xwp-1.0.tar.gz ├── MANIFEST ├── setup.py ├── suba │ ├── aa.py │ ├── bb.py │ └── __init__.py └── subb ├── cc.py ├── dd.py └── __init__.py