知识点
文件操作
<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