打开和关闭文件
open 函数
你必须先用Python内置的open()函数打开一个文件,创建一个file对象,相关的方法才可以调用它进行读写。
语法:
file object = open(file_name [, access_mode][, buffering])
各个参数的细节如下:
- file_name:file_name变量是一个包含了你要访问的文件名称的字符串值。
- access_mode:access_mode决定了打开文件的模式:只读,写入,追加等。这个参数是非强制的,默认文件访问模式为只读(r)。
所有可取值如下:
r: 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb: 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式
r+: 打开一个文件用于读写。文件指针将会放在文件的开头。
rb+:以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w:打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
wb:以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件
w+:打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
wb+:以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件
a:打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab:以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+:打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+:以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。
- buffering:如果buffering的值被设置为0,就不会被寄存。如果buffering的值取1,访问文件时会被寄存。如果将buffering的值设置为大于1的整数,表明了这就是寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。
file对象的属性
直接用实例来说明:
fo=open("foo.txt","wb")#打开一个文件
print"文件名:",fo.name # file.name 返回文件的名称
print"是否关闭:",fo.closed #file.closed如果文件关闭返回ture,否则返回false.
print"访问模式:",fo.mode #file.mode返回被打开文件的访问模式。
print"末尾是否强制加空格:",fo.softspace #file.softspace 如果用print输出后,必须跟一个空格符,则返回False。否则返回Ture。
输出结果为:
文件名:foo.txt
是否关闭:False
访问模式:wb
末尾是否强制加空格:0
file对象方法
- close()方法
file 对象的 close()方法刷新缓冲区里任何还没写入的信息,并关闭该文件,这之后便不能再进行写入。
当一个文件对象的引用被重新指定给另一个文件时,Python 会关闭之前的文件。用 close()方法关闭文件是一个很好的习惯。
语法:
fileobject.close();
列子:
#打开一个文件
fo=open("fo.txt","wb")
print "文件名",fo.name
#关闭打开的文件
fo.close()
输出结果为:
文件名:foo.txt
- write()方法
write()方法可将任何字符串写入一个打开的文件。需要重点注意的是,Python字符串可以是二进制数据,而不是仅仅是文字。
write()方法不会在字符串的结尾添加换行符('\n'):
语法:
fileobject:write(string);
在这里,被传递的参数是要写入到已打开文件的内容。
例子:
# 打开一个文件
fo = open("foo.txt", "wb")
fo.write( "hello,world\I love Python\n");
# 关闭打开的文件
fo.close()
打开文件,会看到下面的结果:
hello world
I love Python
- read()方法
read()方法从一个打开的文件中读取一个字符串。需要重点注意的是,Python字符串可以是二进制数据,而不是仅仅是文字。
语法:
fileObject.read([count]);
在这里,被传递的参数是要从已打开文件中读取的字节计数。该方法从文件的开头开始读入,如果没有传入count,它会尝试尽可能多地读取更多的内容,很可能是直到文件的末尾。
例子:
#打开一个文件
fo.open("foo.txt","r+") #还是用以上我们创建的foo.txt文件
str=fo.read(10);
print "读取的字符串是:",str
#关闭打开的文件
fo.close()
输出结果:
读取的字符是:hello,worl
- tell()方法:文件定位
tell()方法告诉你文件内的当前位置;换句话说,下一次的读写会发生在文件开头这么多字节之后。
- seek() 方法
seek(offset [,from])方法改变当前文件的位置。offset变量表示要移动的字节数。from变量指定开始移动字节的参考位置。
如果from被设为0,这意味着将文件的开头作为移动字节的参考位置。如果设为1,则使用当前的位置作为参考位置。如果它被设为2,那么该文件的末尾将作为参考位置。
例子:
#还是用上面创建的文件foo.txt
fo=open("foo.txt",r+)
str=fo.read(11)
print"读取的字符串是:",str
#查找当前的位置
position=fo.tell()
print"当前文件位置:",position
#把指针再次重新定位到文件开头
position=fo.seek(0,0);
str=fo.read(11)
print"重新读取字符串:",str
#关闭打开的文件
fo.close()
输出的结果:
读取的字符串是:hello,world
当前的位置:11
重新读取字符串:hello,world
延伸
我们最后的一步是调用close()方法关闭文件。文件用完之后必须要关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的。
由于文件读写时都有可能产生IOErro,一旦出错,后面的f.close(),就不会调用。所以,为了保证无论是否出错都能正确的关闭文件,我们可以使用try....finally;来实现:
try:
f=open('/path/to/file','r')
print (f.read())
finally:
if f:
f.close()
但是每次都这样写比较繁琐的,所以Python 引入了with语句来自动帮我们调用close()方法:
with open('path/to/file','r') as f:
print (f.read())
这和前面的try ... finally是一样的,但是代码更佳简洁,并且f.close()方法
已经自动调过了。
- with 是如何工作的呢
上例中”open()”方法是Python自带的,那我们怎么定义自己的类型来使用with语句呢。基本思想是with所求值得对象必须有一个enter()方法,一个exit()方法。紧跟with后面的语句被求值后,返回对象的enter()方法被调用,这个方法的返回值被赋值给as后面的变量。当with后面的代码被全部执行完之后,将调用返回对象的exit()方法。
class Sample:
def __enter__(self):
print("In __enter__()")
return "Foo"
def __exit__(self, type, value, trace):
print("In __exit__()")
def get_sample():
return Sample()
with get_sample() as sample:
print( "sample:", sample)
输出结果
In __enter__()
sample: Foo
In __exit__()
观察输出结果:
- enter()方法被执行
- enter()方法返回的值 - 这个例子中是"Foo",赋值给变量'sample'
- 执行代码块,打印变量"sample"的值为 "Foo"
- exit()方法被调用
with真正强大之处是它可以处理异常。可能你已经注意到Sample类的exit方法有三个参数- val, type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。
class Sample:
def __enter__(self):
return self
def __exit__(self, type, value, trace):
print("type:", type)
print("value", value)
print("trace", trace)
def do_something(self):
bar = 1 / 0
return bar + 10
def get_sample():
return Sample()
with Sample() as sample:
sample.do_something()
输出结果:
Traceback (most recent call last):
type:
File "C:/Users/lkx941013/PycharmProjects/lianxi11/5.py", line 21, in
value division by zero
trace
sample.do_something()
File "C:/Users/lkx941013/PycharmProjects/lianxi11/5.py", line 12, in do_something
bar = 1 / 0
ZeroDivisionError: division by zero
Process finished with exit code 1
这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有enter()和exit()方法即可。此例中,Sample()的enter()方法返回新创建的Sample对象,并赋值给变量sample。
观察执行结果
实际上,在with后面的代码块抛出任何异常时,exit()方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给exit()方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在exit方法当中。
因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单
重命名和删除文件
Python的os模块提供了帮你执行文件处理操作的方法,比如重命名和删除文件。
要使用这个模块,你必须先导入它,然后才可以调用相关的各种功能。
- rename()方法:
rename()方法需要两个参数,当前的文件名和新文件名。
语法:
os.rename(current_file_name, new_file_name)
例子:
下面将重命名的一个已经存在的文件test.txt
import os
# 重命名文件test1.txt到test2.txt。
os.rename( "test1.txt", "test2.txt" )
- remove()方法
你可以用remove()方法删除文件,需要提供要删除的文件名作为参数
语法:
os.remove(file_name)
例子:
下例将删除一个已经存在的文件test2.txt。
import os
# 删除一个已经存在的文件test2.txt
os.remove("test2.txt")
操作文件和目录
操作文件和目录的函数一部分放在os模块中,一部分放在os.path模块中,这一点要注意一下。查看、创建和删除目录可以这么调用
- mkdir()方法
可以使用os模块的mkdir()方法在当前目录下创建新的目录们也可以直接创建一单级目录(见例3)。你需要提供一个包含了要创建的目录名称的参数。
语法:
os.mkdir("newdir")
例子:
下例将在当前目录下创建一个新目录test。
import os
# 创建目录test
os.mkdir("test")
- chdir()方法
可以用chdir()方法来改变当前的目录。chdir()方法需要的一个参数是你想设成当前目录的目录名称。
语法:
os.chdir("newdir")
例子:
下例将进入"/home/newdir"目录
import os
# 将当前目录改为"/home/newdir"
os.chdir("/home/newdir")
- getcwd()方法:
getcwd()方法显示当前的工作目录。
语法:
os.getcwd()
例子:
下例给出当前目录:
import os
# 给出当前的目录
print os.getcwd()
- rmdir()方法
rmdir()方法删除目录,目录名称以参数传递。在删除这个目录之前,它的所有内容应该先被清除。
语法:
os.rmdir('dirname')
例子:
以下是删除" /tmp/test"目录的例子。目录的完全合规的名称必须被给出,否则会在当前目录下搜索该目录。
import os
# 删除”/tmp/test”目录
os.rmdir( "/tmp/test" )
- os.path.join() 方法
把两个路径合成一个时,不要直接拼字符串,而要通过os.path.join()函数,这样可以正确处理不同操作系统的路径分隔符。在Linux/Unix/Mac下,os.path.join()返回这样的字符串:
part-1/part-2
而Windows下会返回这样的字符串:
part-1\part-2
- os.path.split()
同样的道理,要拆分路径时,也不要直接去拆字符串,而要通过os.path.split()函数,这样可以把一个路径拆分为两部分,后一部分总是最后级别的目录或文件名:
>>> os.path.split('/Users/michael/testdir/file.txt')
('/Users/michael/testdir', 'file.txt')
- os.path.splitext()
os.path.splitext()可以直接让你得到文件扩展名,很多时候非常方便:
>>> os.path.splitext('/path/to/file.txt')
('/path/to/file', '.txt')
这些合并、拆分路径的函数并不要求目录和文件要真实存在,它们只对字符串进行操作。
但是复制文件的函数居然在os模块中不存在!原因是复制文件并非由操作系统提供的系统调用。
幸运的是shutil模块提供了copyfile()的函数,你还可以在shutil模块中找到很多实用函数,它们可以看做是os模块的补充。
通过实例掌握知识点
- 列1:创建文件并写入内容
import os
import os.path #os.path 此模块用来操作路径
ls = os.linesep #os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用'\r\n',Linux使用'\n'而Mac使用'\r'。
#获得文件名
filename = input('Enter a file name:')
while True:
if os.path.exists(filename): #os.path.exists()是判断文件路径是否存在
print("ERROR: '%s' already exists" % filename)
else:
break
all = []
print("\nEnter lines ('.' by iteself to quit).\n") #'\n' 是换行的意思
#循环直到用户输入'.'终止,把内容先写入一个数列中
while True:
entry = input('>')
if entry == '.':
break
else:
all.append(entry)
fobj = open(filename, 'w') # 打开文件
fobj.writelines(['%s%s' %(x, ls) for x in all]) #把数列中的内容一行一行的放入文件里
fobj.close() #关闭文件
print("Done!")
输出结果:
Enter a file name:1043
Enter lines ('.' by iteself to quit).
>1043
>study
>group
>.
Done!
下面我们找到这个文件来看看
- 例2:打开上面的1043文件
filename = '1043'
try:
fobj = open(filename, 'r')#以读的方式打开文件
except IOError as e:
print("*** file open error", e)
else:
for eachLine in fobj:
print(eachLine.strip())#strip() 1.语法:str.strip([chars]); 2.返回值是返回移除字符串头尾指定的字符生成的新字符串。3.strip()默认删除空白符
fobj.close()
输出结果:
1043
study
group
- 例3:创建目录
import os
a=os.getcwd()#获取当前路径
print(a)
b=os.listdir(os.getcwd())#获取当前目录中的内容
print(b)
os.mkdir('D:\hel')#只创建单层目录
os.makedirs('D:\helos\he')#创建多级目录
输出结果:
C:\Users\hk\PycharmProjects\lianxi11 #这是输出的a
['.idea', '1.py', '1043', '2.py', '3.py', '4.py', 'a.py', 'b.py', 'c.py', 'd.py', 'hhr', 'kkuu', 'lkgg', 'studypython'] #这是b
查看在自己的D盘中确实有hel文件夹,helos文件夹,并且helos文件夹中有一个he
完!