Python回顾与整理7:文件和输入输出

        主要是下面的内容:

  • 文件对象:内建函数、内建方法、属性

  • 标准文件

  • 文件系统:访问方法、文件执行

  • 持久化存储

  • 标准库中与文件有关的模块




1.文件对象


        文件对象是用来访问文件的接口,而文件只是连续的字节序列,数据的传输经常会用到字节流,无论字节流是由单个字节还是大块数据组成。




2.文件内建函数(open()和file())


        内建函数open()以及file()提供了初始化输入/输出(I/O)操作的通用接口,如果打开文件成功,则会返回一个文件对象,否则会引发IOError异常,open()和file()并没有任何区别,可以任意替换,基本语法如下:

1
file_object  =  open (file_name, access_mode = 'r' , buffering = - 1 )

        说明如下:

  • file_name:包含要打开的文件名的字符串表示,可以是相对路径或绝对路径

  • access_mode:访问模式,可选参数,如果没有指定,默认值为'r'(字符串表示)

        访问模式主要有下面几种:

模式说明
'r'读取,文件必须要存在
'w'写入,文件存在则清空原来文件内容再写入;文件不存在则自动创建该文件并写入内容
'a'追加,文件存在只会在文件后面追加数据;文件不存在则自动创建该文件并写入内容
'+'表示可读可写,但不能单独使用,一般与'r'一起使用
'b'

以二进制模式访问文件,但不能作为第一个字符出现,对于Unix系统来说,可能会被忽略掉,因为Unix系统默认把所有文件当作进制文件,所以使用'b'模式时,一般是希望在所有系统平台上都是用二进制模式来访问文件(比如在Windows上)

'U'

通用换行符支持(UNS),用来处理不同操作系统平台上的换行符(\n,\r或者\r\n),使用该模式时,文件对象的newlines属性会记录它曾“看到的”文件的行结束符,文件刚打开时,程序还没有遇到换行符,newlines值为None,在文件第一行被读取后,它被设置为第一行的结束符,如果遇到其他类型的行结束符,newlines会成为一个包含每种格式的元组。

不过需要注意的是,UNS中用于读取文本文件,没有对应的处理文件输出的方法。默认情况下该模式是打开的,如果不需要,可以在执行脚本文件时使用参数--without-universal-newlines

        常用的访问模式组合如下:

文件对象的访问模式
文件模式操作
r以读方式打开
rU或U以读方式打开,同时提供通用换行符支持
w以写方式打开(必要时清空)
a以追加模式打开(从EOF开始,必要时创建新文件)
r+以读写模式打开
w+以读写模式打开(参见w)
a+以读写模式打开(参见a)
rb 以二进制读模式打开
wb以二进制写模式打开(参见w)
ab以二进制追加模式打开(参见a)
rb+以二进制读写模式打开(参见r+)
wb+以二进制读写模式打开(参见w+)
ab+ 以二进制读写模式打开(参见a+)
  • buffering:用于指示访问文件所采用的缓冲方式,采用默认方式即可

        0表示不缓冲,1表示缓冲一行数据,任何其他大于1的值代表使用给定值作为缓冲区大小。

        



3.文件内建方法


        open()成功执行后会返回一个文件对象,对该文件的所有操作都通过这个句柄来完成,其操作方法如下:


(1)输入

        主要如下:

  • read(size=-1):读取给定数目个字节并以字符串返回,size默认为-1或其他负值时,表示全部读取

1
2
3
4
5
6
7
8
9
10
>>> f  =  open ( 'test.txt' 'r' )
>>> f.readlines()
[ 'xpleafclyyh\n' 'cl\n' ]
>>> f  =  open ( 'test.txt' 'r' )
>>> f.read()
'xpleafclyyh\ncl\n'
>>> f  =  open ( 'test.txt' 'r' )
>>> f.read( 6 )
'xpleaf'
>>> f.close()
  • readline(size=-1):读取文件的一行并以字符串返回,size默认为-1或其他负值时,表示全部读取,给定size值时,如果小于当前行的字节数,则不完整地读取一行,否则则会完整读取该行

1
2
3
4
5
6
7
8
9
10
11
12
>>> f  =  open ( 'test.txt' 'r' )
>>> f.readlines()
[ 'xpleafclyyh\n' 'cl\n' ]
>>> f  =  open ( 'test.txt' 'r' )
>>> f.readline()
'xpleafclyyh\n'
>>> f  =  open ( 'test.txt' 'r' )
>>> f.readline( 6 )
'xpleaf'
>>> f.readline( 10 )
'clyyh\n'
>>> f.close()
  • readlines([size]):以列表的方式返回所有的行,不过在测试时size参数没有起作用

1
2
3
4
>>> f  =  open ( 'test.txt' 'r' )
>>> f.readlines()
[ 'xpleafclyyh\n' 'cl\n' ]
>>> f.close()

        另外还有一个xreadlines()的方法,可以不用全部读取所有的行以节省空间,不过由于现在文件读取可以使用for循环迭代的方式,即for eachLine in file,所以可以不使用xreadlines()即可以节省内存空间。

        在读取操作时可以看到,Pytthon不会自动为我们去掉换行符,所以一般我们这样处理:

1
2
3
=  open ( 'myFile' 'r' )
data  =  [line.strip()  for  line  in  f.readlines()]
f.close()

        同样,在下面的输出中,Python也不会自动为我们加上换行符,这个操作要我们自己完成。


(2)输出

        主要如下:

  • write(str):把数据写入到文件中,需要写入一行数据时可以在字符串后面加行结束符即可,所以输出的方法并没有writeline()

1
2
3
4
5
6
7
8
9
>>> f  =  open ( 'test.txt' 'w' )
>>> f.write( 'xpleaf' )
>>> f.write( 'clyyh\n' )
>>> f.write( 'cl\n' )
>>> f.close()
>>> f  =  open ( 'test.txt' 'r' )
>>> f.readlines()
[ 'xpleafclyyh\n' 'cl\n' ]
>>> f.close()
  • writelines(seq):接受一个字符串列表作为参数,将它们写入文件,不过行结束符并不会被自动加上

1
2
3
4
5
6
7
8
>>> f  =  open ( 'test.txt' 'w' )
>>> data  =  [ 'xpleaf' 'test\n' 'clyyh\n' ]
>>> f.writelines(data)
>>> f.close()
>>> f  =  open ( 'test.txt' 'r' )
>>> f.readlines()
[ 'xpleaftest\n' 'clyyh\n' ]
>>> f.close()


(3)文件内移动

        主要是下面的两个方法:

  • seek(offset[, whence]):移动文件指针到不同的位置,offset字节表示相对于位置whence的偏移量,whence的默认值为0,表示相对于文件的开头,1代表从当前位置算起,2代表从文件末尾算起

  • tell():返回当前文件指针所在的位置

        举例如下:

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
>>> f  =  open ( 'test.txt' 'r' )
>>> f.readlines()
[ 'xpleafclyyh\n' 'cl\n' ]
>>> f.seek( 0 )
>>> f.read( 6 )
'xpleaf'
>>> f.tell()
6
>>> f.seek( 8 )
>>> f.tell()
8
>>> f.read()
'yyh\ncl\n'
>>> f.tell()
15
>>> f.seek( - 3 1 )
>>> f.tell()
12
>>> f.read()
'cl\n'
>>> f.seek( 0 )
>>> f.tell()
0
>>> f.seek( - 3 2 )
>>> f.tell()
12
>>> f.read()
'cl\n'
>>> f.close()


(4)文件迭代

        在Python2.2之后,引进了迭代器和文件迭代,文件对象成为了它们自己的迭代器,因此可以通过使用for循环迭代(for line in file)的方式来取代xreadlines()的功能,这样的话就可以大大节省内存空间。因为文件对象本身就是一个迭代器,所以它有next()方法,并且在迭代完所有数据后会引发StopIteration异常。


(5)其他

        其他内建方法如下:

  • close():通过关闭文件来结束对它的访问,如果不显式地关闭文件,那么可能丢失输出缓冲区的数据

  • flush():直接把内部缓冲区中的数据立刻写入文件

        在执行f.write()的操作时,其实并没有把内容实时地写入到磁盘中,而是保存到内部缓冲区中,在文件关闭或执行flush()时都会保存在磁盘中。

  • flieno():返回打开文件的描述符

1
2
3
>>> f  =  open ( 'welcome.txt' 'r' )
>>> f.fileno()
3
  • isatty():当文件是一个类tty设备时返回True,否则返回False

  • truncate([size]):将文件截取到当前文件指针位置或者到给定size,以字节为单位

        所谓的截取其实就是把当前位置之后的文件内容删除,给定了size参数,表明从第几个字节开始截取(包括该字节),如果size没有给定,则默认从当前位置开始,如下:

1
2
3
4
5
6
7
8
9
10
11
>>> f  =  open ( 'test.txt' 'r+' )
>>> f.read()
'clyyh'
>>> f.truncate()
>>> f.seek( 0 )
>>> f.read()
'clyyh'
>>> f.truncate( 2 )
>>> f.seek( 0 )
>>> f.read()
'cl'


(6)行分隔符与路径分隔符在不同操作系统中的差异

        如下:

  • 行分隔符:在POSIX(Unix系列或Mac OX X)系统上是'\n'字符,在旧的MacOS下是'\r',而DOS和Wind32系统下结合了两者'\r\n'

  • 路径分隔符:POSIX使用'/',DOS和Windows使用'\',旧版本的MacOS使用':'

        如果要创建跨平台的应用时,就需要处理这些差异,不过Python中的os模块已经有相关属性来为我们处理这些差异:

有助于跨平台开发的os模块属性
os模块属性描述
linesep用于在文件中分隔行的字符串
sep用来分隔文件路径名的字符串
pathsep用于分隔文件路径的字符串
curdir当前工作目录的字符串名称
pardir(当前工作目录的)父目录字符串名称

        下面是在Linux操作系统上的例子:

1
2
3
4
5
6
7
8
9
10
11
>>>  import  os
>>> os.linesep
'\n'
>>> os.sep
'/'
>>> os.pathsep
':'
>>> os.curdir
'.'
>>> os.pardir
'..'

        下面是在Windows操作系统上的例子:

1
2
3
4
5
6
7
8
9
10
11
>>>  import  os
>>> os.linesep
'\r\n'
>>> os.sep
'\\'
>>> os.pathsep
';'
>>> os.curdir
'.'
>>> os.pardir
'..'

        不过另外需要注意的是,print语句在输出时会自动为我们添加一个换行符,如果不需要该换行符,可以在输出语句后面加一个逗号','。




4.文件内建属性


        主要如下:

文件对象的属性
属性描述
flie.closed如果文件已经关闭返回True,否则返回False
file.encoding文件所使用的编码——当Unicode字符串被写入数据时,它们将自动使用file.encoding转换为字节字符串;若file.encoding为None时使用系统默认编码
file.mode文件打开时使用的访问模式
file.name

文件名

file.newlines未读取到行分隔符时为None, 只有一种行分隔符时为一个字符串,当文件有多种类型的行结束符时,则为一个包含所有当前所遇到的行结束符的列表
file.softspace为0表示在输出一数据后,要加上一个空格符,1表示不加。这个属性一般程序员用不着,由程序内部使用

        举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> f  =  open ( 'test.txt' 'r+' )
>>> f.read()
'xpleaf\nclyyh\ncl'
>>> f.closed
False
>>> f.encoding
>>> f.mode
'r+'
>>> f.name
'test.txt'
>>> f.newlines
>>> f.softspace
0

        但是可以看到的是,newlines并没有任何输出。




5.标准文件


        只要Python程序一执行,其实就可以访问到下面的这三个标准文件:

  • 标准输入:键盘或磁盘的输入

  • 标准输出:到显示器的缓冲输出

  • 标准错误:到屏幕的非缓冲输出

        注意上面的缓冲指的是open()的第三个参数,而之所以说程序一执行就可以访问这3个标准文件,是因为这些文件预先已经被打开了,只要知道它们的文件句柄主可以随时访问这些文件,Python中可以通过sys模块来访问这些文件的句柄:

  • sys.stdin

  • sys.stdout

  • sys.stderr

        print语句通常是输出到sysy.stdout,而raw_input()则通常是从sys.stdin接收输入,如下:

1
2
3
4
5
6
>>>  import  sys
>>> sys.stdout.write( 'xpleaf\n' )
xpleaf
>>> sys.stdin.readline()
xpleaf
'xpleaf\n'

        其实上面的三个模块的属性也是file文件类型:

1
2
3
4
5
6
>>>  for  stream  in  [sys.stdin, sys.stdout, sys.stderr]:
...    print  type (stream)
... 
< type  'file' >
< type  'file' >
< type  'file' >




6.命令行参数


        在C语言中有argc和argv两个变量,分别代表参数个数和参数向量,在Python中,argc其实就是sys.argv列表的长度,而该列表的第一项sys.argv[0]永远是程序的名称。举例如下:

        程序代码:

1
2
3
4
5
6
#!/usr/bin/env python
 
import  sys
 
print  'you entered' len (sys.argv),  'arguments...'
print  'they were' str (sys.argv)

        执行结果:

1
2
3
xpleaf@leaf:~$ python argv.py xpleaf clyyh cl
you entered  4  arguments...
they were [ 'argv.py' 'xpleaf' 'clyyh' 'cl' ]

        PYthon中关于命令行参数处理的模块如下:

  • getopt模块:不是很精细,但是简单

  • optparse模块:功能强大,更面向对象




7.文件系统


        Python对文件系统的访问通过os模块实现,该模块是Python访问操作系统功能的主要接口,但不是真正的接口,真正的接口是由操作系统提供的,所以可以有如下的关系:

Python程序—os模块—操作系统文件系统接口模块(由os模块根据不同的操作系统进行选择)

        而最常用的是os和os.path,这两个模块提供了与平台和操作系统无关的统一文件系统访问方法,如下:

  • os模块

os模块的文件/目录访问函数
函数描述
文件处理
mkfifo()/mknod()创建命名管道/创建文件系统节点
remove()/unlink()删除文件
rename()/renames()重命名文件
stat(),lstat(),xstat()返回文件信息
symlink()创建符号链接
utime()更新时间戳
tmpfile()创建并打开('w+b')一个新的临时文件
目录/文件夹
chdir()/fchdir()改变当前工作目录/通过一个文件描述符改变当前工作目录
chroot()改变当前进程的根目录
listdir()列出指定目录的文件
getcwd()/getcwdu()返回当前工作目录/功能相同,但返回一个Unicode对象
mkdir()/makedirs()创建目录/创建多层目录
rmdir()/removedirs()删除目录/删除多层目录
访问/权限
access()检验权限模式
chmod()改变权限模式
chown()/lchown()改变owner和group ID/功能相同,但不会跟踪链接
umask()设置默认权限模式
文件描述符操作
open()底层的操作系统open(对于文件,使用标准的内建open()函数)
read()/write()根据文件描述符读取/写入数据
dup()/dup2()复制文件描述符号/功能相同,但是是复制到另一个文件描述符
设备号
makedev()从major和minor设备号创建一个原始设备号
major()/minor()从原始设备号获得major/minior设备号
  • os.path模块

os.path模块中的路径名访问函数
函数描述
分隔
basename()去掉目录路径,返回文件名
dirname()去年文件名,返回目录路径
join()将分离的各部分组合成一个路径名
split()返回(dirname(), basename())元组
splitdrive()返回(dirname, pathname)元组
splitext()返回(filename, extension)元组
信息
getatime()返回最近访问时间
getctime()返回文件创建时间
getmtime()返回最近文件修改时间
getsize()返回文件大小(以字节为单位)
查询
exists()指定路径(文件或目录)是否存在
isabs()指定路径是否为绝对路径
isdir()指定路径是否存在且为一个目录
isfile()指定路径是否存在且为一个文件
islink()指定路径是否存在且为一个符号链接
ismount()指定路径是否存在且为一个挂载点
samefile()两个路径名是否指向同一个文件


        关于os和os.path,一个经典的例子如下:

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
#!/usr/bin/env python
 
import  os
for  tmpdir  in  ( '/tmp' , r 'c:\temp' ):
     if  os.path.isdir(tmpdir):
         break
else :
     print  'no temp directory available'
     tmpdir  =  ''
 
if  tmpdir:
     os.chdir(tmpdir)
     cwd  =  os.getcwd()
     print  '*** current temporary directory'
     print  cwd
 
     print  '*** creating example directory...'
     os.mkdir( 'example' )
     os.chdir( 'example' )
     cwd  =  os.getcwd()
     print  '*** new working directory: '
     print  cwd
     print  '*** original directory listing: '
     print  os.listdir(cwd)
 
     print  '*** creating test file...'
     fobj  =  open ( 'test' 'w' )
     fobj.write( 'foo\n' )
     fobj.write( 'bar\n' )
     fobj.close()
     print  '*** updated directory listing: '
     print  os.listdir(cwd)
 
     print  "*** renaming 'test' to 'filetest.txt' "
     os.rename( 'test' 'filetest.txt' )
     print  '*** updated directory listing: '
     print  os.listdir(cwd)
 
     path  =  os.path.join(cwd, os.listdir(cwd)[ 0 ])
     print  '*** full file pathname'
     print  path
     print  '*** (pathname, basename) =='
     print  os.path.split(path)
     print  '*** (filename, extension) =='
     print  os.path.splitext(os.path.basename(path))
 
     print  '*** displaying file contents: '
     fobj  =  open (path)
     for  eachLine  in  fobj:
         print  eachLine,
     fobj.close()
 
     print  '*** deleting test file'
     os.remove(path)
     print  '*** updated directory listing: '
     print  os.listdir(cwd)
     os.chdir(os.pardir)
     print  '***  deleting test directory'
     os.rmdir( 'example' )
     print  '*** DONE'

        在Linux操作系统执行如下:

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
xpleaf@leaf:~$ python ospathex.py 
*** current temporary directory
/tmp
*** creating example directory...
*** new working directory: 
/tmp/example
*** original directory listing: 
[]
*** creating  test  file ...
*** updated directory listing: 
[ 'test' ]
*** renaming  'test'  to  'filetest.txt' 
*** updated directory listing: 
[ 'filetest.txt' ]
*** full  file  pathname
/tmp/example/filetest .txt
*** (pathname,  basename ) ==
( '/tmp/example' 'filetest.txt' )
*** (filename, extension) ==
( 'filetest' '.txt' )
*** displaying  file  contents: 
foo
bar
*** deleting  test  file
*** updated directory listing: 
[]
***  deleting  test  directory
*** DONE

        在Windows操作系统上执行如下:

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:\Users\xpleaf\Source_code>python ospathex.py
*** current temporary directory
c:\temp
*** creating example directory...
*** new working directory:
c:\temp\example
*** original directory listing:
[]
*** creating test file...
*** updated directory listing:
[ 'test' ]
*** renaming  'test'  to  'filetest.txt'
*** updated directory listing:
[ 'filetest.txt' ]
*** full file pathname
c:\temp\example\filetest.txt
*** (pathname, basename) ==
( 'c:\\temp\\example' 'filetest.txt' )
*** (filename, extension) ==
( 'filetest' '.txt' )
*** displaying file contents:
foo
bar
*** deleting test file
*** updated directory listing:
[]
***  deleting test directory
*** DONE




8.文件执行


        关于如何启动其他程序,以及如何与它们进行通信,或者是Python执行环境的一般信息,可以参考《Python回顾与整理12:执行环境》。




9.永久存储模块


        以二进制数据的形式来存储Python的复杂数据结构(如列表、字典等),主要是pickle和json,其它的在需要用到时查阅即可。




10.相关模块


        在需要使用时查阅即可。




本文转自 xpleaf 51CTO博客,原文链接:http://blog.51cto.com/xpleaf/1757262,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值